-
-
Notifications
You must be signed in to change notification settings - Fork 6
Library to serialize and deserialize Syn syntax trees #25
Comments
I started writing an implementation of this: https://github.com/taiki-e/serde-syn |
I think the output of serde-syn is still a little redundant. {
"items": [
{
"struct": {
"ident": "S",
"fields": {
"named": [
{
"ident": "x",
"colon_token": true,
"ty": {
"path": {
"segments": [
{
"ident": "i32"
}
]
}
}
}
]
}
}
},
{
"fn": {
"ident": "main",
"inputs": [],
"output": null,
"stmts": [
{
"let": {
"pats": [
{
"ident": {
"ident": "s"
}
}
],
"init": {
"struct": {
"path": {
"segments": [
{
"ident": "S"
}
]
},
"fields": [
{
"ident": "x",
"colon_token": true,
"expr": {
"lit": {
"int": "0"
}
}
}
]
}
}
}
},
{
"semi": {
"macro": {
"path": {
"segments": [
{
"ident": "println"
}
]
},
"delimiter": "paren",
"tts": [
{
"lit": "\"{}\""
},
{
"punct": {
"op": ",",
"spacing": "alone"
}
},
{
"ident": "s"
},
{
"punct": {
"op": ".",
"spacing": "alone"
}
},
{
"ident": "x"
}
]
}
}
}
]
}
}
]
} |
Thanks for working on this! This is terrific. My first impression is that the public API is too large:
|
Thanks for the feedback!
Indeed.
The first way is easier, but I'm interested in the second way. Does this probably require the following trait? pub trait Node {
type Adapter: Serialize + for<'de> Deserialize<'de>;
// probably #[doc(hidden)] ?
fn to_adapter(&self) -> Self::Adapter;
// probably #[doc(hidden)] ?
fn from_adapter(adapter: &Self::Adapter) -> Self;
}
#[doc(hidden)]
pub use self::file::File;
impl Node for syn::File {
type Adapter = File;
fn to_adapter(&self) -> Self::Adapter { .. }
fn from_adapter(adapter: &Self::Adapter) -> Self { .. }
}
pub fn serialize<N: Node>(syn_node: &N) -> String {
let serializable = syn_node.to_adapter();
serde_json::to_string_pretty(&serializable).unwrap()
}
pub fn deserialize<N: Node>(json: &str) -> serde_json::Result<N> {
let serializable: N::Adapter = serde_json::from_str(json)?;
let syn_node = N::from_adapter(&serializable);
Ok(syn_node)
}
That makes sense. I opened taiki-e/syn-serde#2 for remove these. |
Yep, that trait would work! The name If you feel adventurous, you could try using syn.json and whatever we come up with for dtolnay/syn#607 to generate most of the trait impls programmatically, leaving handwritten impls only where something needs to be specially handled. |
That's a good name!
I will try that! It would be very nice to me if can generate most of the trait implementations programmatically! |
Here is a programmatic description of the Syn syntax tree that could be useful for generating a lot of the serialization/deserialization library: |
@dtolnay: Sorry for the delay. I've updated crate based on syn 1.0 and published 0.1: https://crates.io/crates/syn-serde |
Nice! This crate is great for what I need, and the API is small and easy to understand. Thanks so much for working on this. I know it was an annoying library to write at times. I added a link to your crate from the readme, and also filed taiki-e/syn-serde#6 for one small issue to follow up. |
For a project, I would like to be able to manipulate Rust syntax trees from a different language. Rather than implementing a Rust parser in the other language, I would like to have Syn parse the code and share the parsed syntax tree as JSON.
This is similar to the use case for rustc's
rustc src/main.rs -Z ast-json
flag.Consider an input file like the following:
rustc currently produces this verbose JSON (click to show).
I think we can take a somewhat more concise approach that aligns better with Syn's syntax tree, something like this:
I would prefer not to do this with
derive(Serialize, Deserialize)
attributes directly in Syn because the data structures that work best for manipulating a syntax tree from Rust code are not necessarily the same as the data structures that make for a nice serialized representation to work with across languages. Serialization will need a similar but not identical set of data structures that derive Serialize and Deserialize, with conversion logic back and forth to Syn types. I would expect it to work something like:The text was updated successfully, but these errors were encountered: