Skip to content

Instantly share code, notes, and snippets.

@neonphog
Created June 28, 2019 23:31
Show Gist options
  • Select an option

  • Save neonphog/f98d31688f23e4b47c2a8c6b974f8923 to your computer and use it in GitHub Desktop.

Select an option

Save neonphog/f98d31688f23e4b47c2a8c6b974f8923 to your computer and use it in GitHub Desktop.
Rust Capnp with Json
/* FROM CAPNP SCHEMA:
struct Message {
union {
msgError @0 :MsgError;
}
struct MsgError {
errorCode @0 :ErrorCode;
errorText @1 :Text;
enum ErrorCode {
unknown @0;
invalidChannelId @1;
}
}
}
*/
extern crate capnp;
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
pub mod p2p_capnp;
use p2p_capnp::message;
use p2p_capnp::message::msg_error;
trait FromCapnp<I, O> {
fn from_capnp(i: I) -> O;
}
trait ToCapnp<W> {
fn to_capnp(&self, w: W);
}
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
pub enum ErrorCode {
Unknown = 0,
InvalidChannelId = 1,
}
impl FromCapnp<msg_error::ErrorCode, ErrorCode> for ErrorCode {
fn from_capnp(i: msg_error::ErrorCode) -> ErrorCode {
return match i as u16 {
1 => ErrorCode::InvalidChannelId,
_ => ErrorCode::Unknown,
};
}
}
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
pub struct MsgError {
pub error_code: ErrorCode,
pub error_text: String,
}
impl<'a> FromCapnp<msg_error::Reader<'a>, MsgError> for MsgError {
fn from_capnp(i: msg_error::Reader) -> MsgError {
return MsgError {
error_code: ErrorCode::from_capnp(i.get_error_code().unwrap()),
error_text: i.get_error_text().unwrap().to_string(),
}
}
}
impl<'a> ToCapnp<msg_error::Builder<'a>> for MsgError {
fn to_capnp(&self, mut w: msg_error::Builder) {
w.set_error_code(match self.error_code {
ErrorCode::InvalidChannelId => msg_error::ErrorCode::InvalidChannelId,
_ => msg_error::ErrorCode::Unknown,
});
w.set_error_text(&self.error_text);
}
}
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
pub enum Message {
Unknown,
MsgError(MsgError),
}
impl<'a> FromCapnp<message::Reader<'a>, Message> for Message {
fn from_capnp(i: message::Reader) -> Message {
match i.which().unwrap() {
message::Which::MsgError(err) => {
return Message::MsgError(MsgError::from_capnp(err.unwrap()));
}
_ => {}
}
Message::Unknown
}
}
impl<'a> ToCapnp<message::Builder<'a>> for Message {
fn to_capnp(&self, w: message::Builder) {
match self {
Message::MsgError(err) => {
err.to_capnp(w.init_msg_error());
}
_ => {}
}
}
}
fn main() {
let msg = Message::MsgError(MsgError {
error_code: ErrorCode::InvalidChannelId,
error_text: "try encoding this".to_string(),
});
let mut data: Vec<u8> = Vec::with_capacity(4069);
{
let mut message = capnp::message::Builder::new_default();
msg.to_capnp(message.init_root::<message::Builder>());
capnp::serialize_packed::write_message(&mut data, &message).unwrap();
}
println!("generated bytes: {:?}", data.as_slice());
let parsed = {
let reader = capnp::serialize_packed::read_message(
&mut std::io::Cursor::new(&data),
capnp::message::ReaderOptions::new()).unwrap();
let message = reader.get_root::<message::Reader>().unwrap();
Message::from_capnp(message)
};
println!("parsed: {:?}", parsed);
let j = serde_json::to_string_pretty(&msg).unwrap();
println!("as_json: {}", j);
let jparsed: Message = serde_json::from_str(&j).unwrap();
println!("from_json: {:?}", jparsed);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment