Skip to content

Commit

Permalink
More work on adding missing API functions, make get return Option
Browse files Browse the repository at this point in the history
Update method names to map new OCaml API
  • Loading branch information
tizoc committed Jun 13, 2021
1 parent d016d4d commit 80f2e76
Show file tree
Hide file tree
Showing 6 changed files with 267 additions and 59 deletions.
11 changes: 6 additions & 5 deletions tezos/new_context/bin/context_action_file_replayer.rs
Expand Up @@ -440,13 +440,14 @@ fn main() -> Result<(), Error> {
);
}
ContextAction::Get { key, value, .. } => {
assert_eq!(value.clone(), context.get(key).unwrap());
// FIXME: value can be `None`, fix ContextAction::Get
assert_eq!(value.clone(), context.find(key).unwrap().unwrap());
}
ContextAction::Mem { key, value, .. } => {
assert_eq!(*value, context.mem(key).unwrap());
}
ContextAction::DirMem { key, value, .. } => {
assert_eq!(*value, context.dirmem(key).unwrap());
assert_eq!(*value, context.mem_tree(key).unwrap());
}
_ => {}
};
Expand Down Expand Up @@ -513,23 +514,23 @@ fn perform_context_action(
// Write actions produce a new context, read actions return the original context
let (context, new_tree_id) = match action {
ContextAction::Get { key, .. } => {
current_context.get(&key)?;
current_context.find(&key)?;
(context, None)
}
ContextAction::Mem { key, .. } => {
current_context.mem(&key)?;
(context, None)
}
ContextAction::DirMem { key, .. } => {
current_context.dirmem(&key)?;
current_context.mem_tree(&key)?;
(context, None)
}
ContextAction::Set {
key,
value,
new_tree_id,
..
} => (current_context.set(&key, value)?, Some(new_tree_id)),
} => (current_context.add(&key, value)?, Some(new_tree_id)),
ContextAction::Copy {
to_key: key,
from_key,
Expand Down
250 changes: 229 additions & 21 deletions tezos/new_context/src/ffi.rs
Expand Up @@ -3,8 +3,9 @@

//! Functions exposed to be called from OCaml

// TODO: init function
// TODO: extend init function

use std::convert::TryFrom;
use std::{marker::PhantomData, rc::Rc};

use ocaml_interop::*;
Expand All @@ -24,6 +25,8 @@ use tezos_api::ocaml_conv::OCamlContextHash;
// but once we catch it on Rust, having the original error value may be useful.

ocaml_export! {
// Index API

fn tezedge_index_init(
rt,
_unit: OCamlRef<()>,
Expand All @@ -40,6 +43,14 @@ ocaml_export! {
OCaml::unit()
}

// TODO: implement
fn tezedge_index_patch_context_get(
rt,
_unit: OCamlRef<()>,
) {
OCaml::unit()
}

// OCaml = val exists : index -> Context_hash.t -> bool Lwt.t
fn tezedge_index_exists(
rt,
Expand Down Expand Up @@ -73,6 +84,8 @@ ocaml_export! {
result.to_ocaml(rt)
}

// Context API

// OCaml = val commit : time:Time.Protocol.t -> ?message:string -> context -> Context_hash.t Lwt.t
fn tezedge_context_commit(
rt,
Expand Down Expand Up @@ -138,14 +151,6 @@ ocaml_export! {
OCaml::unit()
}

// TODO: implement
fn tezedge_index_patch_context_get(
rt,
_unit: OCamlRef<()>,
) {
OCaml::unit()
}

// OCaml = val dir_mem : context -> key -> bool Lwt.t
fn tezedge_context_mem_tree(
rt,
Expand All @@ -156,30 +161,47 @@ ocaml_export! {
let context = context_ptr.as_ref();
let key: ContextKey = key.to_rust(rt);

let result = context.dirmem(&key)
let result = context.mem_tree(&key)
.map_err(|err| format!("{:?}", err));

result.to_ocaml(rt)
}

// OCaml = val get : context -> key -> value option Lwt.t
// OCaml = val find : context -> key -> value option Lwt.t
fn tezedge_context_find(
rt,
context: OCamlRef<TezedgeContext>,
key: OCamlRef<OCamlList<String>>,
) -> OCaml<Result<OCamlBytes, String>> {
) -> OCaml<Result<Option<OCamlBytes>, String>> {
let context_ptr: OCamlToRustPointer<TezedgeContext> = context.to_rust(rt);
let context = context_ptr.as_ref();
let key: ContextKey = key.to_rust(rt);

let result = context.get(&key)
let result = context.find(&key)
.map_err(|err| format!("{:?}", err));

result.to_ocaml(rt)
}

// OCaml = val find_tree : context -> key -> tree option Lwt.t
fn tezedge_context_find_tree(
rt,
context: OCamlRef<TezedgeContext>,
key: OCamlRef<OCamlList<String>>,
) -> OCaml<Result<Option<WorkingTreeRc>, String>> {
let context_ptr: OCamlToRustPointer<TezedgeContext> = context.to_rust(rt);
let _context = context_ptr.as_ref();
let _key: ContextKey = key.to_rust(rt);

//let result = context.find_tree(&key)
// .map_err(|err| format!("{:?}", err));

//result.to_ocaml(rt)
// TODO: complete implementation once tree API is available
Err::<Option<OCamlToRustPointer<WorkingTreeRc>>, String>("unimplemented".to_owned()).to_ocaml(rt)
}

// OCaml = val set : context -> key -> value -> t Lwt.t
// OCaml = val add : context -> key -> value -> t Lwt.t
fn tezedge_context_add(
rt,
context: OCamlRef<TezedgeContext>,
Expand All @@ -191,14 +213,35 @@ ocaml_export! {
let key: ContextKey = key.to_rust(rt);
let value: ContextValue = value.to_rust(rt);

let result = context.set(&key, value)
let result = context.add(&key, value)
.map_err(|err| format!("{:?}", err))
.map(|context| OCamlToRustPointer::alloc_custom(rt, context));

result.to_ocaml(rt)
}

// OCaml = val remove_rec : context -> key -> t Lwt.t
// OCaml = val add_tree : tcontext -> key -> tree -> t Lwt.t
fn tezedge_context_add_tree(
rt,
context: OCamlRef<TezedgeContext>,
key: OCamlRef<OCamlList<String>>,
tree: OCamlRef<WorkingTreeRc>,
) -> OCaml<Result<TezedgeContext, String>> {
let context_ptr: OCamlToRustPointer<TezedgeContext> = context.to_rust(rt);
let _context = context_ptr.as_ref();
let _key: ContextKey = key.to_rust(rt);
let _tree: OCamlToRustPointer<WorkingTreeRc> = tree.to_rust(rt);

//let result = context.add_tree(&key, tree)
// .map_err(|err| format!("{:?}", err))
// .map(|context| OCamlToRustPointer::alloc_custom(rt, context));

// result.to_ocaml(rt)
// TODO: complete implementation once tree API is available
Err::<OCamlToRustPointer<TezedgeContext>, String>("unimplemented".to_owned()).to_ocaml(rt)
}

// OCaml = val remove_ : context -> key -> t Lwt.t
fn tezedge_context_remove(
rt,
context: OCamlRef<TezedgeContext>,
Expand Down Expand Up @@ -236,12 +279,177 @@ ocaml_export! {
}

// TODO: fold
// type key_or_dir = [`Key of key | `Dir of key]
// (** [fold ?depth t root ~init ~f] recursively folds over the trees
// and values of [t]. The [f] callbacks are called with a key relative
// to [root]. [f] is never called with an empty key for values; i.e.,
// folding over a value is a no-op.
//
// Elements are traversed in lexical order of keys.
//
// (** [fold] iterates over elements under a path (not recursive). Iteration order
// is nondeterministic. *)
// val fold :
// context -> key -> init:'a -> f:(key_or_dir -> 'a -> 'a Lwt.t) -> 'a Lwt.t
// The depth is 0-indexed. If [depth] is set (by default it is not), then [f]
// is only called when the conditions described by the parameter is true:
//
// - [Eq d] folds over nodes and contents of depth exactly [d].
// - [Lt d] folds over nodes and contents of depth strictly less than [d].
// - [Le d] folds over nodes and contents of depth less than or equal to [d].
// - [Gt d] folds over nodes and contents of depth strictly more than [d].
// - [Ge d] folds over nodes and contents of depth more than or equal to [d]. *)
// val fold :
// ?depth:[`Eq of int | `Le of int | `Lt of int | `Ge of int | `Gt of int] ->
// t ->
// key ->
// init:'a ->
// f:(key -> tree -> 'a -> 'a Lwt.t) ->
// 'a Lwt.t

// Tree API

// OCaml = val hash : tree -> Context_hash.t
fn tezedge_tree_hash(
rt,
tree: OCamlRef<WorkingTreeRc>,
) -> OCaml<Result<OCamlContextHash, String>> {
let tree_ptr: OCamlToRustPointer<WorkingTreeRc> = tree.to_rust(rt);
let tree = tree_ptr.as_ref();

let result = match tree.get_staged_root_hash() {
Err(err) => Err(format!("{:?}", err)),
Ok(hash) => ContextHash::try_from(hash.as_ref()).map_err(|err| format!("{:?}", err))
};

result.to_ocaml(rt)
}

// OCaml = val mem : tree -> key -> bool Lwt.t
fn tezedge_tree_mem(
rt,
tree: OCamlRef<WorkingTreeRc>,
key: OCamlRef<OCamlList<String>>,
) -> OCaml<Result<bool, String>> {
let tree_ptr: OCamlToRustPointer<WorkingTreeRc> = tree.to_rust(rt);
let tree = tree_ptr.as_ref();
let key: ContextKey = key.to_rust(rt);

let result = tree.mem(&key)
.map_err(|err| format!("{:?}", err));

result.to_ocaml(rt)
}

// TODO: implement
fn tezedge_tree_empty(
rt,
_unit: OCamlRef<()>,
) {
OCaml::unit()
}

// OCaml = val dir_mem : tree -> key -> bool Lwt.t
fn tezedge_tree_mem_tree(
rt,
tree: OCamlRef<WorkingTreeRc>,
key: OCamlRef<OCamlList<String>>,
) -> OCaml<Result<bool, String>> {
let tree_ptr: OCamlToRustPointer<WorkingTreeRc> = tree.to_rust(rt);
let tree = tree_ptr.as_ref();
let key: ContextKey = key.to_rust(rt);

let result = tree.mem_tree(&key)
.map_err(|err| format!("{:?}", err));

result.to_ocaml(rt)
}

// OCaml = val find : tree -> key -> value option Lwt.t
fn tezedge_tree_find(
rt,
tree: OCamlRef<WorkingTreeRc>,
key: OCamlRef<OCamlList<String>>,
) -> OCaml<Result<Option<OCamlBytes>, String>> {
let tree_ptr: OCamlToRustPointer<WorkingTreeRc> = tree.to_rust(rt);
let tree = tree_ptr.as_ref();
let key: ContextKey = key.to_rust(rt);

let result = tree.find(&key)
.map_err(|err| format!("{:?}", err));

result.to_ocaml(rt)
}

// OCaml = val find_tree : tree -> key -> tree option Lwt.t
fn tezedge_tree_find_tree(
rt,
tree: OCamlRef<WorkingTreeRc>,
key: OCamlRef<OCamlList<String>>,
) -> OCaml<Result<Option<WorkingTreeRc>, String>> {
let tree_ptr: OCamlToRustPointer<WorkingTreeRc> = tree.to_rust(rt);
let _tree = tree_ptr.as_ref();
let _key: ContextKey = key.to_rust(rt);

//let result = context.find_tree(&key)
// .map_err(|err| format!("{:?}", err));

//result.to_ocaml(rt)
// TODO: complete implementation once tree API is available
Err::<Option<OCamlToRustPointer<WorkingTreeRc>>, String>("unimplemented".to_owned()).to_ocaml(rt)
}

// OCaml = val add : tree -> key -> value -> t Lwt.t
fn tezedge_tree_add(
rt,
tree: OCamlRef<WorkingTreeRc>,
key: OCamlRef<OCamlList<String>>,
value: OCamlRef<OCamlBytes>,
) -> OCaml<Result<WorkingTreeRc, String>> {
let tree_ptr: OCamlToRustPointer<WorkingTreeRc> = tree.to_rust(rt);
let tree = tree_ptr.as_ref();
let key: ContextKey = key.to_rust(rt);
let value: ContextValue = value.to_rust(rt);

let result = tree.add(&key, value)
.map_err(|err| format!("{:?}", err))
.map(|tree| OCamlToRustPointer::alloc_custom(rt, Rc::new(tree)));

result.to_ocaml(rt)
}

// OCaml = val add_tree : tree -> key -> tree -> t Lwt.t
fn tezedge_tree_add_tree(
rt,
tree: OCamlRef<WorkingTreeRc>,
key: OCamlRef<OCamlList<String>>,
new_tree: OCamlRef<WorkingTreeRc>,
) -> OCaml<Result<WorkingTreeRc, String>> {
let tree_ptr: OCamlToRustPointer<WorkingTreeRc> = tree.to_rust(rt);
let _tree = tree_ptr.as_ref();
let _key: ContextKey = key.to_rust(rt);
let _new_tree: OCamlToRustPointer<WorkingTreeRc> = new_tree.to_rust(rt);

//let result = context.add_tree(&key, tree)
// .map_err(|err| format!("{:?}", err))
// .map(|context| OCamlToRustPointer::alloc_custom(rt, context));

// result.to_ocaml(rt)
// TODO: complete implementation once tree API is available
Err::<OCamlToRustPointer<WorkingTreeRc>, String>("unimplemented".to_owned()).to_ocaml(rt)
}

// OCaml = val remove : tree -> key -> t Lwt.t
fn tezedge_tree_remove(
rt,
tree: OCamlRef<WorkingTreeRc>,
key: OCamlRef<OCamlList<String>>,
) -> OCaml<Result<WorkingTreeRc, String>> {
let tree_ptr: OCamlToRustPointer<WorkingTreeRc> = tree.to_rust(rt);
let tree = tree_ptr.as_ref();
let key: ContextKey = key.to_rust(rt);

let result = tree.delete(&key)
.map_err(|err| format!("{:?}", err))
.map(|tree| OCamlToRustPointer::alloc_custom(rt, Rc::new(tree)));

result.to_ocaml(rt)
}
}

use tezos_sys::initialize_tezedge_context_callbacks;
Expand Down

0 comments on commit 80f2e76

Please sign in to comment.