Update attenuations
This commit is contained in:
parent
12eaeb8f62
commit
833be7b293
|
@ -101,7 +101,7 @@ pub enum Expr {
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
enum RewriteTemplate {
|
enum RewriteTemplate {
|
||||||
Filter {
|
Accept {
|
||||||
pattern_template: AnyValue,
|
pattern_template: AnyValue,
|
||||||
},
|
},
|
||||||
Rewrite {
|
Rewrite {
|
||||||
|
@ -110,6 +110,16 @@ enum RewriteTemplate {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
enum CaveatTemplate {
|
||||||
|
Alts {
|
||||||
|
alternatives: Vec<RewriteTemplate>,
|
||||||
|
},
|
||||||
|
Reject {
|
||||||
|
pattern_template: AnyValue,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
enum Symbolic {
|
enum Symbolic {
|
||||||
Reference(String),
|
Reference(String),
|
||||||
|
@ -174,55 +184,77 @@ fn tlit(value: AnyValue) -> sturdy::Template {
|
||||||
sturdy::Template::Lit(Box::new(sturdy::Lit { value }))
|
sturdy::Template::Lit(Box::new(sturdy::Lit { value }))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_attenuation(r: &Record<AnyValue>) -> io::Result<Option<(String, Vec<RewriteTemplate>)>> {
|
fn parse_rewrite(raw_base_name: &AnyValue, e: &AnyValue) -> io::Result<RewriteTemplate> {
|
||||||
|
if let Some(fields) = e.value().as_simple_record("accept", Some(1)) {
|
||||||
|
return Ok(RewriteTemplate::Accept {
|
||||||
|
pattern_template: fields[0].clone(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(fields) = e.value().as_simple_record("rewrite", Some(2)) {
|
||||||
|
return Ok(RewriteTemplate::Rewrite {
|
||||||
|
pattern_template: fields[0].clone(),
|
||||||
|
template_template: fields[1].clone(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Err(bad_instruction(&format!("Bad rewrite in attenuation of {:?}: {:?}", raw_base_name, e)))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_caveat(raw_base_name: &AnyValue, e: &AnyValue) -> io::Result<CaveatTemplate> {
|
||||||
|
if let Some(fields) = e.value().as_simple_record("or", Some(1)) {
|
||||||
|
let raw_rewrites = match fields[0].value().as_sequence() {
|
||||||
|
None => Err(bad_instruction(&format!(
|
||||||
|
"Alternatives in <or> in attenuation of {:?} must have sequence of rewrites; got {:?}",
|
||||||
|
raw_base_name,
|
||||||
|
fields[0])))?,
|
||||||
|
Some(vs) => vs,
|
||||||
|
};
|
||||||
|
let alternatives =
|
||||||
|
raw_rewrites.iter().map(|r| parse_rewrite(raw_base_name, r)).collect::<Result<Vec<_>, _>>()?;
|
||||||
|
return Ok(CaveatTemplate::Alts{ alternatives });
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(fields) = e.value().as_simple_record("reject", Some(1)) {
|
||||||
|
return Ok(CaveatTemplate::Reject{ pattern_template: fields[0].clone() });
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Ok(r) = parse_rewrite(raw_base_name, e) {
|
||||||
|
return Ok(CaveatTemplate::Alts { alternatives: vec![r] });
|
||||||
|
}
|
||||||
|
|
||||||
|
Err(bad_instruction(&format!("Bad caveat in attenuation of {:?}: {:?}", raw_base_name, e)))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_attenuation(r: &Record<AnyValue>) -> io::Result<Option<(String, Vec<CaveatTemplate>)>> {
|
||||||
if r.label() != &AnyValue::symbol("*") {
|
if r.label() != &AnyValue::symbol("*") {
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
}
|
}
|
||||||
|
|
||||||
if r.fields().len() != 2 {
|
if r.fields().len() != 2 {
|
||||||
Err(bad_instruction(&format!(
|
Err(bad_instruction(&format!(
|
||||||
"Attenuation requires a reference and a sequence of rewrites; got {:?}",
|
"Attenuation requires a reference and a sequence of caveats; got {:?}",
|
||||||
r)))?;
|
r)))?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let base_name = match r.fields()[0].value().as_symbol().map(|s| analyze(&s)) {
|
let raw_base_name = &r.fields()[0];
|
||||||
|
let base_name = match raw_base_name.value().as_symbol().map(|s| analyze(&s)) {
|
||||||
Some(Symbolic::Reference(s)) => s,
|
Some(Symbolic::Reference(s)) => s,
|
||||||
_ => Err(bad_instruction(&format!(
|
_ => Err(bad_instruction(&format!(
|
||||||
"Attenuation must have variable reference as first argument; got {:?}",
|
"Attenuation must have variable reference as first argument; got {:?}",
|
||||||
r.fields()[0])))?,
|
raw_base_name)))?,
|
||||||
};
|
};
|
||||||
|
|
||||||
let raw_alternatives = match r.fields()[1].value().as_sequence() {
|
let raw_caveats = match r.fields()[1].value().as_sequence() {
|
||||||
None => Err(bad_instruction(&format!(
|
None => Err(bad_instruction(&format!(
|
||||||
"Attenuation of {:?} must have sequence of rewrites; got {:?}",
|
"Attenuation of {:?} must have sequence of caveats; got {:?}",
|
||||||
r.fields()[0],
|
raw_base_name,
|
||||||
r.fields()[1])))?,
|
r.fields()[1])))?,
|
||||||
Some(vs) => vs,
|
Some(vs) => vs,
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut alternatives = Vec::new();
|
let caveats = raw_caveats.iter().map(|c| parse_caveat(raw_base_name, c)).collect::<Result<Vec<_>, _>>()?;
|
||||||
|
Ok(Some((base_name, caveats)))
|
||||||
for e in raw_alternatives.iter() {
|
|
||||||
match e.value().as_simple_record("filter", Some(1)) {
|
|
||||||
Some(fields) =>
|
|
||||||
alternatives.push(RewriteTemplate::Filter {
|
|
||||||
pattern_template: fields[0].clone()
|
|
||||||
}),
|
|
||||||
None => match e.value().as_simple_record("rewrite", Some(2)) {
|
|
||||||
Some(fields) =>
|
|
||||||
alternatives.push(RewriteTemplate::Rewrite {
|
|
||||||
pattern_template: fields[0].clone(),
|
|
||||||
template_template: fields[1].clone(),
|
|
||||||
}),
|
|
||||||
None => Err(bad_instruction(&format!(
|
|
||||||
"Bad rewrite in attenuation of {:?}: {:?}",
|
|
||||||
r.fields()[0],
|
|
||||||
e)))?,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(Some((base_name, alternatives)))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'env> PatternInstantiator<'env> {
|
impl<'env> PatternInstantiator<'env> {
|
||||||
|
@ -250,8 +282,8 @@ impl<'env> PatternInstantiator<'env> {
|
||||||
},
|
},
|
||||||
|
|
||||||
Value::Record(r) => match parse_attenuation(r)? {
|
Value::Record(r) => match parse_attenuation(r)? {
|
||||||
Some((base_name, alternatives)) =>
|
Some((base_name, caveats)) =>
|
||||||
dlit(self.env.eval_attenuation(base_name, alternatives)?),
|
dlit(self.env.eval_attenuation(base_name, caveats)?),
|
||||||
None => match self.maybe_binder_with_pattern(r)? {
|
None => match self.maybe_binder_with_pattern(r)? {
|
||||||
Some(pat) => pat,
|
Some(pat) => pat,
|
||||||
None => {
|
None => {
|
||||||
|
@ -359,8 +391,8 @@ impl Env {
|
||||||
},
|
},
|
||||||
|
|
||||||
Value::Record(r) => match parse_attenuation(r)? {
|
Value::Record(r) => match parse_attenuation(r)? {
|
||||||
Some((base_name, alternatives)) =>
|
Some((base_name, caveats)) =>
|
||||||
self.eval_attenuation(base_name, alternatives)?,
|
self.eval_attenuation(base_name, caveats)?,
|
||||||
None =>
|
None =>
|
||||||
Value::Record(Record(r.fields_vec().iter().map(|a| self.instantiate_value(a))
|
Value::Record(Record(r.fields_vec().iter().map(|a| self.instantiate_value(a))
|
||||||
.collect::<Result<Vec<_>, _>>()?)).wrap(),
|
.collect::<Result<Vec<_>, _>>()?)).wrap(),
|
||||||
|
@ -398,7 +430,7 @@ impl Env {
|
||||||
fn eval_attenuation(
|
fn eval_attenuation(
|
||||||
&self,
|
&self,
|
||||||
base_name: String,
|
base_name: String,
|
||||||
alternatives: Vec<RewriteTemplate>,
|
caveats: Vec<CaveatTemplate>,
|
||||||
) -> io::Result<AnyValue> {
|
) -> io::Result<AnyValue> {
|
||||||
let base_value = self.lookup(&base_name, "attenuation-base variable")?;
|
let base_value = self.lookup(&base_name, "attenuation-base variable")?;
|
||||||
match base_value.value().as_embedded() {
|
match base_value.value().as_embedded() {
|
||||||
|
@ -406,9 +438,7 @@ impl Env {
|
||||||
"Value to be attenuated is {:?} but must be capability",
|
"Value to be attenuated is {:?} but must be capability",
|
||||||
base_value))),
|
base_value))),
|
||||||
Some(base_cap) => {
|
Some(base_cap) => {
|
||||||
match base_cap.attenuate(&sturdy::Attenuation(vec![
|
match base_cap.attenuate(&caveats.iter().map(|c| self.instantiate_caveat(c)).collect::<Result<Vec<_>, _>>()?) {
|
||||||
self.instantiate_caveat(&alternatives)?]))
|
|
||||||
{
|
|
||||||
Ok(derived_cap) => Ok(AnyValue::domain(derived_cap)),
|
Ok(derived_cap) => Ok(AnyValue::domain(derived_cap)),
|
||||||
Err(caveat_error) =>
|
Err(caveat_error) =>
|
||||||
Err(bad_instruction(&format!("Attenuation of {:?} failed: {:?}",
|
Err(bad_instruction(&format!("Attenuation of {:?} failed: {:?}",
|
||||||
|
@ -517,35 +547,50 @@ impl Env {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn instantiate_caveat(
|
fn instantiate_rewrite(
|
||||||
&self,
|
&self,
|
||||||
alternatives: &Vec<RewriteTemplate>,
|
rw: &RewriteTemplate,
|
||||||
) -> io::Result<sturdy::Caveat> {
|
) -> io::Result<sturdy::Rewrite> {
|
||||||
let mut rewrites = Vec::new();
|
match rw {
|
||||||
for rw in alternatives {
|
RewriteTemplate::Accept { pattern_template } => {
|
||||||
match rw {
|
let (_binding_names, pattern) = self.instantiate_pattern(pattern_template)?;
|
||||||
RewriteTemplate::Filter { pattern_template } => {
|
Ok(sturdy::Rewrite {
|
||||||
let (_binding_names, pattern) = self.instantiate_pattern(pattern_template)?;
|
pattern: embed_pattern(&P::Pattern::DBind(Box::new(P::DBind { pattern }))),
|
||||||
rewrites.push(sturdy::Rewrite {
|
template: sturdy::Template::TRef(Box::new(sturdy::TRef { binding: 0.into() })),
|
||||||
pattern: embed_pattern(&P::Pattern::DBind(Box::new(P::DBind { pattern }))),
|
})
|
||||||
template: sturdy::Template::TRef(Box::new(sturdy::TRef { binding: 0.into() })),
|
}
|
||||||
})
|
RewriteTemplate::Rewrite { pattern_template, template_template } => {
|
||||||
}
|
let (binding_names, pattern) = self.instantiate_pattern(pattern_template)?;
|
||||||
RewriteTemplate::Rewrite { pattern_template, template_template } => {
|
Ok(sturdy::Rewrite {
|
||||||
let (binding_names, pattern) = self.instantiate_pattern(pattern_template)?;
|
pattern: embed_pattern(&pattern),
|
||||||
rewrites.push(sturdy::Rewrite {
|
template: self.instantiate_template(&binding_names, template_template)?,
|
||||||
pattern: embed_pattern(&pattern),
|
})
|
||||||
template: self.instantiate_template(&binding_names, template_template)?,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if rewrites.len() == 1 {
|
}
|
||||||
Ok(sturdy::Caveat::Rewrite(Box::new(rewrites.pop().unwrap())))
|
|
||||||
} else {
|
fn instantiate_caveat(
|
||||||
Ok(sturdy::Caveat::Alts(Box::new(sturdy::Alts {
|
&self,
|
||||||
alternatives: rewrites,
|
c: &CaveatTemplate,
|
||||||
})))
|
) -> io::Result<sturdy::Caveat> {
|
||||||
|
match c {
|
||||||
|
CaveatTemplate::Alts { alternatives } => {
|
||||||
|
let mut rewrites =
|
||||||
|
alternatives.iter().map(|r| self.instantiate_rewrite(r)).collect::<Result<Vec<_>, _>>()?;
|
||||||
|
if rewrites.len() == 1 {
|
||||||
|
Ok(sturdy::Caveat::Rewrite(Box::new(rewrites.pop().unwrap())))
|
||||||
|
} else {
|
||||||
|
Ok(sturdy::Caveat::Alts(Box::new(sturdy::Alts {
|
||||||
|
alternatives: rewrites,
|
||||||
|
})))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CaveatTemplate::Reject { pattern_template } => {
|
||||||
|
Ok(sturdy::Caveat::Reject(Box::new(
|
||||||
|
sturdy::Reject {
|
||||||
|
pattern: embed_pattern(&self.instantiate_pattern(pattern_template)?.1),
|
||||||
|
})))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -584,18 +629,19 @@ impl Env {
|
||||||
},
|
},
|
||||||
|
|
||||||
Value::Record(r) => match parse_attenuation(r)? {
|
Value::Record(r) => match parse_attenuation(r)? {
|
||||||
Some((base_name, alternatives)) =>
|
Some((base_name, caveats)) =>
|
||||||
match find_bound(&base_name) {
|
match find_bound(&base_name) {
|
||||||
Some(i) =>
|
Some(i) =>
|
||||||
sturdy::Template::TAttenuate(Box::new(sturdy::TAttenuate {
|
sturdy::Template::TAttenuate(Box::new(sturdy::TAttenuate {
|
||||||
template: sturdy::Template::TRef(Box::new(sturdy::TRef {
|
template: sturdy::Template::TRef(Box::new(sturdy::TRef {
|
||||||
binding: i.into(),
|
binding: i.into(),
|
||||||
})),
|
})),
|
||||||
attenuation: sturdy::Attenuation(vec![
|
attenuation: caveats.iter()
|
||||||
self.instantiate_caveat(&alternatives)?]),
|
.map(|c| self.instantiate_caveat(c))
|
||||||
|
.collect::<Result<Vec<_>, _>>()?,
|
||||||
})),
|
})),
|
||||||
None =>
|
None =>
|
||||||
tlit(self.eval_attenuation(base_name, alternatives)?),
|
tlit(self.eval_attenuation(base_name, caveats)?),
|
||||||
},
|
},
|
||||||
None => {
|
None => {
|
||||||
// TODO: properly consolidate constant templates into literals.
|
// TODO: properly consolidate constant templates into literals.
|
||||||
|
|
|
@ -2270,11 +2270,11 @@ impl Cap {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Yields a fresh `Cap` for `self`'s `underlying`, copying the
|
/// Yields a fresh `Cap` for `self`'s `underlying`, copying the
|
||||||
/// existing attenuation of `self` to the new `Cap` and adding
|
/// existing attenuation of `self` to the new `Cap` and adding the
|
||||||
/// `attenuation` to it.
|
/// `caveats` to it.
|
||||||
pub fn attenuate(&self, attenuation: &sturdy::Attenuation) -> Result<Arc<Self>, CaveatError> {
|
pub fn attenuate(&self, caveats: &[sturdy::Caveat]) -> Result<Arc<Self>, CaveatError> {
|
||||||
let mut r = Cap { attenuation: self.attenuation.clone(), .. self.clone() };
|
let mut r = Cap { attenuation: self.attenuation.clone(), .. self.clone() };
|
||||||
r.attenuation.extend(attenuation.check()?);
|
r.attenuation.extend(sturdy::Caveat::check_many(caveats)?);
|
||||||
Ok(Arc::new(r))
|
Ok(Arc::new(r))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2282,7 +2282,7 @@ impl Cap {
|
||||||
/// `a` is filtered out, or `Some(_)` if it is accepted (and
|
/// `a` is filtered out, or `Some(_)` if it is accepted (and
|
||||||
/// possibly transformed).
|
/// possibly transformed).
|
||||||
pub fn rewrite(&self, mut a: AnyValue) -> Option<AnyValue> {
|
pub fn rewrite(&self, mut a: AnyValue) -> Option<AnyValue> {
|
||||||
for c in &self.attenuation {
|
for c in self.attenuation.iter().rev() {
|
||||||
match c.rewrite(&a) {
|
match c.rewrite(&a) {
|
||||||
Some(v) => a = v,
|
Some(v) => a = v,
|
||||||
None => return None,
|
None => return None,
|
||||||
|
|
|
@ -580,7 +580,7 @@ impl Membranes {
|
||||||
match self.exported.oid_map.get(&oid) {
|
match self.exported.oid_map.get(&oid) {
|
||||||
None => self.exported.insert_inert_entity(t, oid),
|
None => self.exported.insert_inert_entity(t, oid),
|
||||||
Some(ws) => {
|
Some(ws) => {
|
||||||
let attenuated_obj = ws.obj.attenuate(&sturdy::Attenuation(attenuation))
|
let attenuated_obj = ws.obj.attenuate(&attenuation)
|
||||||
.map_err(|e| {
|
.map_err(|e| {
|
||||||
io::Error::new(
|
io::Error::new(
|
||||||
io::ErrorKind::InvalidInput,
|
io::ErrorKind::InvalidInput,
|
||||||
|
|
|
@ -16,7 +16,10 @@ pub type CheckedRewrite = (usize, Pattern, Template);
|
||||||
/// A safety-checked [`Caveat`]: none of the errors enumerated in
|
/// A safety-checked [`Caveat`]: none of the errors enumerated in
|
||||||
/// `CaveatError` apply.
|
/// `CaveatError` apply.
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
|
#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
|
||||||
pub struct CheckedCaveat { alts: Vec<CheckedRewrite> }
|
pub enum CheckedCaveat {
|
||||||
|
Alts(Vec<CheckedRewrite>),
|
||||||
|
Reject(Pattern),
|
||||||
|
}
|
||||||
|
|
||||||
/// Represents any detected error in a [`Caveat`]; that is, in a
|
/// Represents any detected error in a [`Caveat`]; that is, in a
|
||||||
/// [`Pattern`] or a [`Template`].
|
/// [`Pattern`] or a [`Template`].
|
||||||
|
@ -28,43 +31,44 @@ pub enum CaveatError {
|
||||||
BindingUnderNegation,
|
BindingUnderNegation,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Attenuation {
|
impl Caveat {
|
||||||
/// Yields `Ok(())` iff `self` has no [`CaveatError`].
|
/// Yields `Ok(())` iff `caveats` have no [`CaveatError`].
|
||||||
pub fn validate(&self) -> Result<(), CaveatError> {
|
pub fn validate_many(caveats: &[Caveat]) -> Result<(), CaveatError> {
|
||||||
for c in &self.0 { c.validate()? }
|
for c in caveats { c.validate()? }
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Yields a vector of [`CheckedCaveat`s][CheckedCaveat] iff
|
|
||||||
/// `self` has no [`CaveatError`].
|
|
||||||
pub fn check(&self) -> Result<Vec<CheckedCaveat>, CaveatError> {
|
|
||||||
self.0.iter().map(Caveat::check).collect()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Caveat {
|
|
||||||
/// Yields `Ok(())` iff `self` has no [`CaveatError`].
|
/// Yields `Ok(())` iff `self` has no [`CaveatError`].
|
||||||
pub fn validate(&self) -> Result<(), CaveatError> {
|
pub fn validate(&self) -> Result<(), CaveatError> {
|
||||||
match self {
|
match self {
|
||||||
Caveat::Rewrite(b) => (&**b).validate(),
|
Caveat::Rewrite(b) => (&**b).validate(),
|
||||||
Caveat::Alts(b) => (&**b).alternatives.iter().map(Rewrite::validate).collect::<Result<(), _>>(),
|
Caveat::Alts(b) => (&**b).alternatives.iter().map(Rewrite::validate).collect::<Result<(), _>>(),
|
||||||
|
Caveat::Reject(_) => Ok(()),
|
||||||
|
Caveat::Unknown(_) => Ok(()), /* it's valid to have unknown caveats, they just won't pass anything */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Yields a vector of [`CheckedCaveat`s][CheckedCaveat] iff
|
||||||
|
/// `caveats` have no [`CaveatError`].
|
||||||
|
pub fn check_many(caveats: &[Caveat]) -> Result<Vec<CheckedCaveat>, CaveatError> {
|
||||||
|
caveats.iter().map(Caveat::check).collect()
|
||||||
|
}
|
||||||
|
|
||||||
/// Yields a [`CheckedCaveat`] iff `self` has no [`CaveatError`].
|
/// Yields a [`CheckedCaveat`] iff `self` has no [`CaveatError`].
|
||||||
pub fn check(&self) -> Result<CheckedCaveat, CaveatError> {
|
pub fn check(&self) -> Result<CheckedCaveat, CaveatError> {
|
||||||
match self {
|
match self {
|
||||||
Caveat::Rewrite(b) =>
|
Caveat::Rewrite(b) =>
|
||||||
Ok(CheckedCaveat {
|
Ok(CheckedCaveat::Alts(vec![ (*b).check()? ])),
|
||||||
alts: vec![ (*b).check()? ]
|
|
||||||
}),
|
|
||||||
Caveat::Alts(b) => {
|
Caveat::Alts(b) => {
|
||||||
let Alts { alternatives } = &**b;
|
let Alts { alternatives } = &**b;
|
||||||
Ok(CheckedCaveat {
|
Ok(CheckedCaveat::Alts(
|
||||||
alts: alternatives.into_iter().map(Rewrite::check)
|
alternatives.into_iter().map(Rewrite::check)
|
||||||
.collect::<Result<Vec<CheckedRewrite>, CaveatError>>()?
|
.collect::<Result<Vec<CheckedRewrite>, CaveatError>>()?))
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
Caveat::Reject(b) =>
|
||||||
|
Ok(CheckedCaveat::Reject(b.pattern.clone())),
|
||||||
|
Caveat::Unknown(_) =>
|
||||||
|
Ok(CheckedCaveat::Reject(Pattern::PDiscard(Box::new(PDiscard)))),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -187,7 +191,7 @@ impl Template {
|
||||||
match self {
|
match self {
|
||||||
Template::TAttenuate(b) => {
|
Template::TAttenuate(b) => {
|
||||||
let TAttenuate { template, attenuation } = &**b;
|
let TAttenuate { template, attenuation } = &**b;
|
||||||
attenuation.validate()?;
|
Caveat::validate_many(attenuation)?;
|
||||||
Ok(template.implied_binding_count()?)
|
Ok(template.implied_binding_count()?)
|
||||||
}
|
}
|
||||||
Template::TRef(b) => match usize::try_from(&(&**b).binding) {
|
Template::TRef(b) => match usize::try_from(&(&**b).binding) {
|
||||||
|
@ -273,12 +277,24 @@ impl Rewrite {
|
||||||
impl CheckedCaveat {
|
impl CheckedCaveat {
|
||||||
/// Rewrites `a` using the patterns/templates contained in `self`.
|
/// Rewrites `a` using the patterns/templates contained in `self`.
|
||||||
pub fn rewrite(&self, a: &_Any) -> Option<_Any> {
|
pub fn rewrite(&self, a: &_Any) -> Option<_Any> {
|
||||||
for (n, p, t) in &self.alts {
|
match self {
|
||||||
let mut bindings = Vec::with_capacity(*n);
|
CheckedCaveat::Alts(alts) => {
|
||||||
if let true = p.matches(a, &mut bindings) {
|
for (n, p, t) in alts {
|
||||||
return t.instantiate(&bindings);
|
let mut bindings = Vec::with_capacity(*n);
|
||||||
|
if p.matches(a, &mut bindings) {
|
||||||
|
return t.instantiate(&bindings);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
},
|
||||||
|
CheckedCaveat::Reject(pat) => {
|
||||||
|
let mut bindings = Vec::with_capacity(0);
|
||||||
|
if pat.matches(a, &mut bindings) {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(a.clone())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,6 +48,14 @@ fn signature(key: &[u8], data: &[u8]) -> Vec<u8> {
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn chain_signature(key: &[u8], chain: &[Caveat]) -> Vec<u8> {
|
||||||
|
let mut key = key.to_vec();
|
||||||
|
for c in chain {
|
||||||
|
key = signature(&key, &encode(&language().unparse(c)));
|
||||||
|
}
|
||||||
|
key
|
||||||
|
}
|
||||||
|
|
||||||
pub fn new_key() -> Vec<u8> {
|
pub fn new_key() -> Vec<u8> {
|
||||||
let mut buf = vec![0; KEY_LENGTH];
|
let mut buf = vec![0; KEY_LENGTH];
|
||||||
getrandom(&mut buf).expect("successful random number generation");
|
getrandom(&mut buf).expect("successful random number generation");
|
||||||
|
@ -83,24 +91,15 @@ impl SturdyRef {
|
||||||
unattenuated_target: &_Ptr,
|
unattenuated_target: &_Ptr,
|
||||||
) -> Result<_Ptr, ValidationError> {
|
) -> Result<_Ptr, ValidationError> {
|
||||||
self.validate(key).map_err(ValidationError::SignatureError)?;
|
self.validate(key).map_err(ValidationError::SignatureError)?;
|
||||||
let mut attenuation = Vec::new();
|
|
||||||
// TODO:: Make sure of the ordering here!!
|
|
||||||
for a in self.caveat_chain.iter().rev() {
|
|
||||||
attenuation.extend(a.0.iter().rev().cloned());
|
|
||||||
}
|
|
||||||
let target = unattenuated_target
|
let target = unattenuated_target
|
||||||
.attenuate(&Attenuation(attenuation))
|
.attenuate(&self.caveat_chain)
|
||||||
.map_err(ValidationError::AttenuationError)?;
|
.map_err(ValidationError::AttenuationError)?;
|
||||||
Ok(target)
|
Ok(target)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn validate(&self, key: &[u8]) -> Result<(), MacError> {
|
pub fn validate(&self, key: &[u8]) -> Result<(), MacError> {
|
||||||
let SturdyRef { oid, caveat_chain, sig } = self;
|
let SturdyRef { oid, caveat_chain, sig } = self;
|
||||||
let mut key = key.to_vec();
|
let key = chain_signature(&signature(&key, &encode(oid)), caveat_chain);
|
||||||
key = signature(&key, &encode(oid));
|
|
||||||
for c in caveat_chain {
|
|
||||||
key = signature(&key, &encode(&language().unparse(c)));
|
|
||||||
}
|
|
||||||
if &key == sig {
|
if &key == sig {
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
|
@ -108,13 +107,13 @@ impl SturdyRef {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn attenuate(&self, attenuation: &Attenuation) -> Result<Self, CaveatError> {
|
pub fn attenuate(&self, attenuation: &[Caveat]) -> Result<Self, CaveatError> {
|
||||||
attenuation.validate()?;
|
Caveat::validate_many(attenuation)?;
|
||||||
let SturdyRef { oid, caveat_chain, sig } = self;
|
let SturdyRef { oid, caveat_chain, sig } = self;
|
||||||
let oid = oid.clone();
|
let oid = oid.clone();
|
||||||
let mut caveat_chain = caveat_chain.clone();
|
let mut caveat_chain = caveat_chain.clone();
|
||||||
caveat_chain.push(attenuation.clone());
|
caveat_chain.extend(attenuation.iter().cloned());
|
||||||
let sig = signature(&sig, &encode(&language().unparse(attenuation)));
|
let sig = chain_signature(&sig, attenuation);
|
||||||
Ok(SturdyRef { oid, caveat_chain, sig })
|
Ok(SturdyRef { oid, caveat_chain, sig })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue