paritytech / parity-scale-codec

Lightweight, efficient, binary serialization and deserialization codec
Apache License 2.0
245 stars 95 forks source link

Constrained decode #112

Open bkchr opened 5 years ago

bkchr commented 5 years ago

We maybe should provide an interface for constrained decoding. We currently don't have any ideas how this could look like.

See https://github.com/paritytech/parity-scale-codec/pull/106 for more information.

bkchr commented 5 years ago

If someone wants to take this, I would propose to create a new crate that sits on top of parity-scale-codec.

gui1117 commented 5 years ago

it seems to me contrained decode is just about adding some assert during the decoding process.

One idea would be a trait:

trait DecodeConstrained {
  type Constraints;
  fn decode_constrained(input, constraints: Constraint) {
    // depending on constraints do some assert during the decode
  }
}

one example would be:

impl DecodeConstrained for Vec<T> {
type Constrained = struct {
  max_limite: Option<u32>,
  on_new_element: Option<callback: Fn(&vec<T>) -> bool>
}
}

but that might be inefficient for decoding a vec then. But that can be handy to derive your own decode_constrained:

#[derive(DecodeConstrained)]
struct MyStruct {
  #[constraint("... callback that returns a bool depending on field")]
  field: signature,
  #[constraint("... callback that returns a bool depending on field and field2")]
  field2: signed_content,
  #[constraint(optional_constrained_field)]
  field3: Vec<T>, 
  #[constraint(struct Constrained { max_limit: Some(3), Default::default() })]
  field4: Vec<T>, 
  field5: Vec<T>,
}

// derives into:

struct MyStructConstraint {
  callback_field: Option<..>,
  callback_field2: Option<..>,
  constraint_field3: Option<<Vec<T> as ConstrainedDecode>::Constraints>,
}

// and during derivation of decode_constrained:
// it decodes field4 with the constrain max_limit=3
// and it decodes field5 just using decode and not decode_constrained