Skip to content

Commit

Permalink
Cleanup after simplifying promises
Browse files Browse the repository at this point in the history
  • Loading branch information
expede committed Feb 22, 2024
1 parent 66efbda commit 322b2c6
Show file tree
Hide file tree
Showing 42 changed files with 878 additions and 386 deletions.
9 changes: 1 addition & 8 deletions src/ability.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,6 @@
//! field may include a promise pointing at another invocation. Once fully
//! resolved ("ready"), they must be validatable against the delegation chain.
// FIXME feature flag each?
// FIXME ability implementers guide (e.g. serde deny fields)
//

pub mod ucan;

#[cfg(feature = "ability-crud")]
Expand All @@ -53,12 +49,9 @@ pub mod preset;

pub mod arguments;
pub mod command;
pub mod parse;

#[cfg(target_arch = "wasm32")]
pub mod js;

// // TODO move to crate::wasm? or hide behind "dynamic" feature flag?
pub mod dynamic;

// FIXME macro to derive promise versions & delagted builder versions
// ... also maybe Ipld
20 changes: 7 additions & 13 deletions src/ability/arguments/named.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::ipld;
use crate::{invocation::promise::Pending, ipld};
use libipld_core::ipld::Ipld;
use serde::{Deserialize, Serialize};
use std::collections::BTreeMap;
Expand Down Expand Up @@ -293,20 +293,14 @@ impl From<Named<Ipld>> for Named<ipld::Promised> {
}

impl TryFrom<Named<ipld::Promised>> for Named<Ipld> {
type Error = Named<ipld::Promised>;
type Error = Pending;

fn try_from(named: Named<ipld::Promised>) -> Result<Self, Self::Error> {
// FIXME lots of clone
// FIXME idea: what if they implemet a is_resoled, and then the try_from?
// This lets us check by ref, and then do the conversion and unwrap
named
.iter()
.try_fold(Named::new(), |mut acc, (ref k, v)| {
let ipld = v.clone().try_into().map_err(|_| ())?;
acc.insert(k.to_string(), ipld);
Ok(acc)
})
.map_err(|()| named.clone())
named.iter().try_fold(Named::new(), |mut acc, (ref k, v)| {
let ipld = v.clone().try_into()?;
acc.insert(k.to_string(), ipld);
Ok(acc)
})
}
}

Expand Down
43 changes: 0 additions & 43 deletions src/ability/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,6 @@
//! }
//! ```
use crate::ability::arguments;
use libipld_core::ipld::Ipld;
use std::fmt;
use thiserror::Error;

/// Attach a `cmd` field to a type
///
/// Commands are the `cmd` field of a UCAN, and set the shape of the `args` field.
Expand Down Expand Up @@ -55,44 +50,6 @@ pub trait Command {
const COMMAND: &'static str;
}

// FIXME definitely needs a better name
// pub trait ParseAbility: TryFrom<arguments::Named<Ipld>> {
pub trait ParseAbility: Sized {
type ArgsErr: fmt::Debug;

fn try_parse(
cmd: &str,
args: arguments::Named<Ipld>,
) -> Result<Self, ParseAbilityError<Self::ArgsErr>>;
}

#[derive(Debug, Clone, Error)]
pub enum ParseAbilityError<E> {
#[error("Unknown command: {0}")]
UnknownCommand(String),

#[error(transparent)]
InvalidArgs(#[from] E),
}

impl<T: Command + TryFrom<arguments::Named<Ipld>>> ParseAbility for T
where
<T as TryFrom<arguments::Named<Ipld>>>::Error: fmt::Debug,
{
type ArgsErr = <T as TryFrom<arguments::Named<Ipld>>>::Error;

fn try_parse(
cmd: &str,
args: arguments::Named<Ipld>,
) -> Result<Self, ParseAbilityError<<Self as TryFrom<arguments::Named<Ipld>>>::Error>> {
if cmd != T::COMMAND {
return Err(ParseAbilityError::UnknownCommand(cmd.to_string()));
}

Self::try_from(args).map_err(ParseAbilityError::InvalidArgs)
}
}

// NOTE do not export; this is used to limit the Hierarchy
// interface to [Parentful] and [Parentless] while enabling [Dynamic]
// FIXME ^^^^ NOT ANYMORE?
Expand Down
46 changes: 45 additions & 1 deletion src/ability/crud.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,8 @@ pub use parents::*;
use crate::{
ability::{
arguments,
command::{ParseAbility, ParseAbilityError, ToCommand},
command::ToCommand,
parse::{ParseAbility, ParseAbilityError, ParsePromised},
},
delegation::Delegable,
invocation::promise::Resolvable,
Expand Down Expand Up @@ -90,6 +91,49 @@ pub enum Promised {
Destroy(destroy::Promised),
}

impl ParsePromised for Promised {
type PromisedArgsError = ();

fn try_parse_promised(
cmd: &str,
args: arguments::Named<ipld::Promised>,
) -> Result<Self, ParseAbilityError<Self::PromisedArgsError>> {
match create::Promised::try_parse_promised(cmd, args.clone()) {
Ok(create) => return Ok(Promised::Create(create)),
Err(ParseAbilityError::InvalidArgs(_)) => {
return Err(ParseAbilityError::InvalidArgs(()))
}
Err(ParseAbilityError::UnknownCommand(_)) => (),
}

match read::Promised::try_parse_promised(cmd, args.clone()) {
Ok(read) => return Ok(Promised::Read(read)),
Err(ParseAbilityError::InvalidArgs(_)) => {
return Err(ParseAbilityError::InvalidArgs(()))
}
Err(ParseAbilityError::UnknownCommand(_)) => (),
}

match update::Promised::try_parse_promised(cmd, args.clone()) {
Ok(update) => return Ok(Promised::Update(update)),
Err(ParseAbilityError::InvalidArgs(_)) => {
return Err(ParseAbilityError::InvalidArgs(()))
}
Err(ParseAbilityError::UnknownCommand(_)) => (),
}

match destroy::Promised::try_parse_promised(cmd, args) {
Ok(destroy) => return Ok(Promised::Destroy(destroy)),
Err(ParseAbilityError::InvalidArgs(_)) => {
return Err(ParseAbilityError::InvalidArgs(()))
}
Err(ParseAbilityError::UnknownCommand(_)) => (),
}

Err(ParseAbilityError::UnknownCommand(cmd.into()))
}
}

impl Delegable for Ready {
type Builder = Builder;
}
Expand Down
20 changes: 1 addition & 19 deletions src/ability/crud/any.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
//! "Any" CRUD ability (superclass of all CRUD abilities)
use crate::{
ability::{
arguments,
command::{Command, ParseAbility, ParseAbilityError},
},
ability::{arguments, command::Command},
proof::{error::OptionalFieldError, parentless::NoParents, same::CheckSame},
};
use libipld_core::{error::SerdeError, ipld::Ipld, serde as ipld_serde};
Expand Down Expand Up @@ -95,21 +92,6 @@ impl TryFrom<arguments::Named<Ipld>> for Any {

impl NoParents for Any {}

// impl ParseAbility for Any {
// type ArgsErr = ();
//
// fn try_parse(
// cmd: &str,
// args: arguments::Named<Ipld>,
// ) -> Result<Self, ParseAbilityError<Self::ArgsErr>> {
// if cmd != Self::COMMAND {
// return Err(ParseAbilityError::CommandMismatch);
// }
//
// Self::try_from(args).map_err(|_| ParseAbilityError::Args(Self::COMMAND))
// }
// }

impl CheckSame for Any {
type Error = OptionalFieldError;

Expand Down
92 changes: 53 additions & 39 deletions src/ability/crud/create.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ use crate::{
ipld,
proof::{checkable::Checkable, parentful::Parentful, parents::CheckParents, same::CheckSame},
};
use libipld_core::{cid::Cid, error::SerdeError, ipld::Ipld, serde as ipld_serde};
use libipld_core::ipld::Ipld;
use serde::Serialize;
use std::{collections::BTreeMap, path::PathBuf};
use std::path::PathBuf;

// FIXME deserialize instance

Expand Down Expand Up @@ -123,31 +123,57 @@ impl Command for Promised {
const COMMAND: &'static str = COMMAND;
}

// impl TryFrom<Ipld> for Ready {
// type Error = (); // FIXME
//
// fn try_from(ipld: Ipld) -> Result<Self, Self::Error> {
// if let Ipld::Map(mut map) = ipld {
// if map.len() > 2 {
// return Err(()); // FIXME
// }
//
// Ok(Generic {
// path: map
// .remove("path")
// .map(|ipld| P::try_from(ipld).map_err(|_| ()))
// .transpose()?,
//
// args: map
// .remove("args")
// .map(|ipld| A::try_from(ipld).map_err(|_| ()))
// .transpose()?,
// })
// } else {
// Err(()) // FIXME
// }
// }
// }
impl TryFrom<arguments::Named<ipld::Promised>> for Promised {
type Error = ();

fn try_from(arguments: arguments::Named<ipld::Promised>) -> Result<Self, Self::Error> {
let mut path = None;
let mut args = None;

for (k, prom) in arguments {
match k.as_str() {
"path" => match prom {
ipld::Promised::String(s) => {
path = Some(promise::Resolves::Ok(
promise::PromiseOk::Fulfilled(PathBuf::from(s)).into(),
));
}
ipld::Promised::WaitOk(cid) => {
path = Some(promise::PromiseOk::Pending(cid).into());
}
ipld::Promised::WaitErr(cid) => {
path = Some(promise::PromiseErr::Pending(cid).into());
}
ipld::Promised::WaitAny(cid) => {
todo!() // FIXME // path = Some(promise::PromiseAny::Pending(cid).into());
}
_ => return Err(()),
},

"args" => {
args = match prom {
ipld::Promised::Map(map) => {
Some(promise::PromiseOk::Fulfilled(arguments::Named(map)).into())
}
ipld::Promised::WaitOk(cid) => {
Some(promise::PromiseOk::Pending(cid).into())
}
ipld::Promised::WaitErr(cid) => {
Some(promise::PromiseErr::Pending(cid).into())
}
ipld::Promised::WaitAny(cid) => {
todo!() // FIXME // Some(promise::PromiseAny::Pending(cid).into())
}
_ => return Err(()),
}
}
_ => return Err(()),
}
}

Ok(Promised { path, args })
}
}

impl TryFrom<arguments::Named<Ipld>> for Ready {
type Error = ();
Expand Down Expand Up @@ -254,18 +280,6 @@ impl From<Ready> for Promised {
}
}

// FIXME may want to name this something other than a TryFrom
// impl From<Promised> for Builder {
// fn from(promised: Promised) -> Self {
// Builder {
// path: promised.path.and_then(|x| x.try_resolve().ok()),
// args: promised
// .args
// .and_then(|x| x.try_resolve().ok()?.try_into().ok()),
// }
// }
// }

impl promise::Resolvable for Ready {
type Promised = Promised;
}
Expand Down
38 changes: 35 additions & 3 deletions src/ability/crud/destroy.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
//! Destroy a resource.
use super::parents::MutableParents;
use crate::{
ability::{arguments, command::Command},
Expand All @@ -9,9 +10,7 @@ use crate::{
};
use libipld_core::ipld::Ipld;
use serde::Serialize;
use std::{collections::BTreeMap, path::PathBuf};

// FIXME deserialize instance
use std::path::PathBuf;

/// A helper for creating lifecycle instances of `crud/create` with the correct shape.
#[derive(Debug, Clone, PartialEq, Serialize)]
Expand Down Expand Up @@ -101,6 +100,39 @@ pub struct Promised {
pub path: Option<promise::Resolves<PathBuf>>,
}

impl TryFrom<arguments::Named<ipld::Promised>> for Promised {
type Error = ();

fn try_from(arguments: arguments::Named<ipld::Promised>) -> Result<Self, Self::Error> {
let mut path = None;

for (k, prom) in arguments {
match k.as_str() {
"path" => match prom {
ipld::Promised::String(s) => {
path = Some(promise::Resolves::Ok(
promise::PromiseOk::Fulfilled(PathBuf::from(s)).into(),
));
}
ipld::Promised::WaitOk(cid) => {
path = Some(promise::PromiseOk::Pending(cid).into());
}
ipld::Promised::WaitErr(cid) => {
path = Some(promise::PromiseErr::Pending(cid).into());
}
ipld::Promised::WaitAny(cid) => {
todo!() // FIXME // path = Some(promise::PromiseAny::Pending(cid).into());
}
_ => return Err(()),
},
_ => return Err(()),
}
}

Ok(Promised { path })
}
}

const COMMAND: &'static str = "crud/destroy";

Check failure on line 136 in src/ability/crud/destroy.rs

View workflow job for this annotation

GitHub Actions / run-checks (stable)

constants have by default a `'static` lifetime

Check failure on line 136 in src/ability/crud/destroy.rs

View workflow job for this annotation

GitHub Actions / run-checks (nightly)

constants have by default a `'static` lifetime

impl Command for Ready {
Expand Down
3 changes: 2 additions & 1 deletion src/ability/crud/parents.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ use super::error::ParentError;
use crate::{
ability::{
arguments,
command::{ParseAbility, ParseAbilityError, ToCommand},
command::ToCommand,
parse::{ParseAbility, ParseAbilityError},
},
proof::{parents::CheckParents, same::CheckSame},
};
Expand Down
Loading

0 comments on commit 322b2c6

Please sign in to comment.