Skip to content

Instantly share code, notes, and snippets.

@pimeys
Last active February 5, 2019 15:18
Show Gist options
  • Save pimeys/c220c9cf82668e7c1cd8db044e19715b to your computer and use it in GitHub Desktop.
Save pimeys/c220c9cf82668e7c1cd8db044e19715b to your computer and use it in GitHub Desktop.
/// Add to Cargo.toml:
/// serde = "1.0"
/// serde_derive = "1.0"
/// serde_yaml = "0.8"
/// serde_json = "1.0"
use serde_derive::Deserialize;
use serde_json::{json, self};
#[derive(Deserialize, Debug)]
struct SchemaTemplate {
pub name: String,
pub models: Vec<ModelTemplate>
}
#[derive(Debug)]
struct Schema<'a> {
pub name: String,
pub models: Vec<Model<'a>>,
}
#[derive(Deserialize, Debug)]
struct ModelTemplate {
pub name: String
}
#[derive(Debug)]
struct Model<'a> {
pub name: String,
pub schema: &'a Schema<'a>,
}
impl<'a> ModelTemplate {
pub fn build(self, schema: &'a Schema<'a>) -> Model<'a> {
Model {
name: self.name,
schema: schema,
}
}
}
impl<'a> Into<Schema<'a>> for SchemaTemplate {
fn into(self) -> Schema<'a> {
let schema = Schema {
name: self.name,
models: Vec::new(),
};
self.models.into_iter().for_each(|mt| {
schema.models.push(mt.build(&schema));
});
schema
}
}
impl<'a> Model<'a> {
pub fn print_schema(&self) {
println!("{}", self.schema.name);
}
}
impl<'a> Schema<'a> {
pub fn find_model(&self, name: &str) -> Option<&'a Model<'a>> {
self.models.iter().find(|model| model.name == name)
}
}
fn main() {
let json = json!({
"name": "test",
"models": [{"name": "testo"}]
});
let template: SchemaTemplate = serde_json::from_value(json).unwrap();
let schema: Schema = template.into();
let model = schema.find_model("testo").unwrap();
model.print_schema();
}
@pimeys
Copy link
Author

pimeys commented Feb 5, 2019

use serde_derive::Deserialize;
use serde_json::{json, self};
use std::{rc::Rc, cell::RefCell};

type SchemaRef = Rc<RefCell<Schema>>;

#[derive(Deserialize, Debug)]
struct SchemaTemplate {
    pub name: String,
    pub models: Vec<ModelTemplate>
}

#[derive(Debug)]
struct Schema {
    pub name: String,
    pub models: Vec<Model>,
}

#[derive(Deserialize, Debug)]
struct ModelTemplate {
    pub name: String
}

#[derive(Debug)]
struct Model {
    pub name: String,
    pub schema: SchemaRef,
}

impl ModelTemplate {
    pub fn build(self, schema: SchemaRef) -> Model {
        Model {
            name: self.name,
            schema: schema,
        }
    }
}

impl Into<SchemaRef> for SchemaTemplate {
    fn into(self) -> SchemaRef {
        let schema = Rc::new(RefCell::new(Schema {
            name: self.name,
            models: Vec::new(),
        }));

        self.models.into_iter().for_each(|mt| {
            schema.borrow_mut().models.push(mt.build(schema.clone()));
        });
        
        schema
    }
}

impl Model {
    pub fn print_schema(&self) {
        println!("{}", self.schema.borrow().name);
    }
}

impl Schema {
    pub fn find_model(&self, name: &str) -> Option<&Model> {
        self.models.iter().find(|model| model.name == name)
    }
}

fn main() {
    let json = json!({
        "name": "test",
        "models": [{"name": "testo"}]
    });
    
    let template: SchemaTemplate = serde_json::from_value(json).unwrap();
    let schema: SchemaRef = template.into();
    let schema_borrow = schema.borrow();
    let model = schema_borrow.find_model("testo").unwrap();
    
    model.print_schema();
}

@pimeys
Copy link
Author

pimeys commented Feb 5, 2019

Questions:

  1. Is it possible to get the first example to work without taking the escape route from the second example.
  2. How is second example different from the first? Are there any downsides with this approach.
  3. How would you make the second example threadsafe
  4. What happens if you call dbg!(schema_borrow); in the last line of the main function? Is there a way to fix this?
  5. The second example might leak memory. Why is that?

http://flyingfrogblog.blogspot.com/2013/10/herb-sutters-favorite-c-10-liner.html

@pimeys
Copy link
Author

pimeys commented Feb 5, 2019

The question number 4 is to find a nice library for this.

The question number 5 is easier with valgrind. It is very important to learn how to use it and how to catch memory leaks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment