Some stuff on the js bindings for the rust legacy message implementation:
extern crate ssb_legacy_msg_data;
extern crate ssb_legacy_msg;
extern crate ssb_multiformats;
fn foo() {
// Parsing a legacy value into a dynamically typed enum:
let _ = ssb_legacy_msg_data::json::from_slice::<ssb_legacy_msg_data::value::Value>(bytes)?;
// Parsing a legacy value into a dynamically typed enum, validating that it can serve as the
// content of a message:
let _ = ssb_legacy_msg_data::json::from_slice::<ssb_legacy_msg_data::value::ContentValue>(bytes)?;
// The same can be done for parsing into js objects, by implementing the serde::Deserialize
// trait for js objects. All n-api errors can be propagated via the `Error::custom` function,
// so no need for debug asserts.
//
// Js API:
// - decodeLegacyJson(buf) -> JsValue (throws on error)
// - ssb_legacy_msg_data::json::from_slice::<napi::JsValue>()
// - decodeLegacyJsonContent(buf) -> JsValue (throws on error)
// - ssb_legacy_msg_data::json::from_slice::<napi::JsContentValue>()
// Serializing anything that implements `serde::Serialize` into the signing encoding.
let _ = ssb_legacy_msg_data::json::to_vec(val, false)?; // can also do `to_string`
// Serializing anything that implements `serde::Serialize` into the transport encoding.
let _ = ssb_legacy_msg_data::json::to_vec(val, true)?; // can also do `to_string`
// These can error if data is invalid (e.g. a float is an infinity), the js API should throw
// accordingly.
// To enable this, implement `serde::Serialize` for the js value type.
// All n-api errors can be propagate via `"Error::custom"` again.
//
// Js API:
// - encodeJsonSigning(js_value) -> JsBuffer (throws on error)
// - encodeJsonTransport(js_value) -> JsBuffer (throws on error)
// Note that nothing enforces deduplication or correct serialization order of object entries.
// You can simply use n-api's default iteration order and hope that it matches that of
// JSON.stringify (precisely defined [here](https://spec.scuttlebutt.nz/datamodel.html#signing-encoding-objects)).
// When the cbor stuff is done, all of the above can also be done for cbor (by literally
// substituting "cbor" for "json")
// Parsing a legacy message (as opposed to free-form data):
let _ = ssb_legacy_msg::json::from_legacy::<ContentValue>(bytes)
// The js binding can internally do `ssb_legacy_msg::json::from_legacy::<JsContentValue>(bytes)`,
// then create another js object, initializing its members from the `Message<JsContentValue>`.
// (if this was unclear, feel free to ask. Well, that actually applies to everything here)
//
// Js API:
// decodeMessageJson(buf) -> JsValue (throws on error)
// Encoding a legacy message into the signing encoding:
let _ = ssb_legacy_msg::json::to_legacy_vec(&msg, false)?;
// Encoding a legacy message into the transport encoding:
let _ = ssb_legacy_msg::json::to_legacy_vec(&msg, true)?;
// Js encoding can simply reuse js `encodeJsonSigning` and `encodeJsonTransport`, since js ssb
// stores messages as regular objects.
// Verification: All public functions in `ssb_legacy_msg::verify` can be exposed in js as well,
// using js buffers and numbers as appropriate. Multiformats need to be converted to their
// legacy encodings, and then put into js strings (which are utf-16 rather than rust's utf-8),
// so there might be another converion in there.
}