Skip to content

Commit

Permalink
Add Candid assist feature in candid_parser (#509)
Browse files Browse the repository at this point in the history
* candid assist

* fix

* fix

* indent

* add auto-completion

* refactor

* bump

* patch ctrlc

* fix

* fix

* changelog
  • Loading branch information
chenyan-dfinity committed Jan 3, 2024
1 parent 7b45d8a commit a6cc9e6
Show file tree
Hide file tree
Showing 14 changed files with 663 additions and 32 deletions.
49 changes: 46 additions & 3 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 15 additions & 1 deletion Changelog.md
@@ -1,14 +1,28 @@

# Changelog

## 2023-01-03

### Candid 0.10.2

* Fix display `IDLValue::Blob` to allow "\n\t" in ascii characters.

### candid_parser 0.1.2

* Add an "assist" feature. Given a type, construct Candid value in the terminal with interactive dialogue.

### didc 0.3.6

* Add `didc assist` command.
* Fix `didc decode --format blob`.

## 2023-12-15

### Candid 0.10.1

* Add `candid::types::value::try_from_candid_type` to convert Rust type to `IDLValue`.
* Display `IDLValue::Blob` in ascii character only when the whole blob are ascii characters.


### candid_parser 0.1.1

* Add `import service` in parser to allow merging services.
Expand Down
2 changes: 1 addition & 1 deletion rust/candid/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "candid"
version = "0.10.1"
version = "0.10.2"
edition = "2021"
authors = ["DFINITY Team"]
description = "Candid is an interface description language (IDL) for interacting with canisters running on the Internet Computer."
Expand Down
6 changes: 1 addition & 5 deletions rust/candid/src/de.rs
Expand Up @@ -373,11 +373,7 @@ impl<'de> Deserializer<'de> {
let mut bytes = vec![0u8];
let int = match self.wire_type.as_ref() {
TypeInner::Int => Int::decode(&mut self.input).map_err(Error::msg)?,
TypeInner::Nat => Int(Nat::decode(&mut self.input)
.map_err(Error::msg)?
.0
.try_into()
.map_err(Error::msg)?),
TypeInner::Nat => Int(Nat::decode(&mut self.input).map_err(Error::msg)?.0.into()),
t => return Err(Error::subtype(format!("{t} cannot be deserialized to int"))),
};
bytes.extend_from_slice(&int.0.to_signed_bytes_le());
Expand Down
2 changes: 1 addition & 1 deletion rust/candid/src/error.rs
Expand Up @@ -14,7 +14,7 @@ pub struct Label {

#[derive(Debug, Error)]
pub enum Error {
#[error("binary parser error: {}", .0.get(0).map_or_else(|| "io error".to_string(), |f| format!("{} at byte offset {}", f.message, f.pos/2)))]
#[error("binary parser error: {}", .0.first().map_or_else(|| "io error".to_string(), |f| format!("{} at byte offset {}", f.message, f.pos/2)))]
Binread(Vec<Label>),

#[error("Subtyping error: {0}")]
Expand Down
4 changes: 3 additions & 1 deletion rust/candid/src/pretty/candid.rs
Expand Up @@ -340,7 +340,9 @@ pub mod value {
Opt(v) => write!(f, "opt {v:?}"),
Blob(b) => {
write!(f, "blob \"")?;
let is_ascii = b.iter().all(|c| (0x20u8..=0x7eu8).contains(c));
let is_ascii = b
.iter()
.all(|c| (0x20u8..=0x7eu8).contains(c) || [0x09, 0x0a, 0x0d].contains(c));
if is_ascii {
for v in b.iter() {
write!(f, "{}", pp_char(*v))?;
Expand Down
3 changes: 2 additions & 1 deletion rust/candid/src/types/internal.rs
Expand Up @@ -316,7 +316,8 @@ impl fmt::Display for TypeInner {
write!(f, "{:?}", self)
}
}
pub(crate) fn text_size(t: &Type, limit: i32) -> Result<i32, ()> {
#[allow(clippy::result_unit_err)]
pub fn text_size(t: &Type, limit: i32) -> Result<i32, ()> {
use TypeInner::*;
if limit <= 1 {
return Err(());
Expand Down
2 changes: 1 addition & 1 deletion rust/candid/src/types/subtype.rs
Expand Up @@ -110,7 +110,7 @@ fn subtype_(
Ok(())
}
(Service(ms1), Service(ms2)) => {
let meths: HashMap<_, _> = ms1.iter().map(|(name, ty)| (name, ty)).collect();
let meths: HashMap<_, _> = ms1.iter().cloned().collect();
for (name, ty2) in ms2 {
match meths.get(name) {
Some(ty1) => subtype_(report, gamma, env, ty1, ty2).with_context(|| {
Expand Down
2 changes: 1 addition & 1 deletion rust/candid_derive/src/func.rs
Expand Up @@ -50,7 +50,7 @@ pub(crate) fn candid_method(attrs: Vec<Meta>, fun: ItemFn) -> Result<TokenStream
));
}
if attrs.is_init {
match (rets.len(), rets.get(0).map(|x| x.as_str())) {
match (rets.len(), rets.first().map(|x| x.as_str())) {
(0, None) | (1, Some("Self")) => {
if let Some(init) = INIT.lock().unwrap().as_mut() {
*init = Some(args);
Expand Down
9 changes: 6 additions & 3 deletions rust/candid_parser/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "candid_parser"
version = "0.1.1"
version = "0.1.2"
edition = "2021"
authors = ["DFINITY Team"]
description = "Candid is an interface description language (IDL) for interacting with canisters running on the Internet Computer. This crate contains the parser and the binding generator for Candid."
Expand Down Expand Up @@ -37,7 +37,9 @@ fake = { version = "2.4", optional = true }
rand = { version = "0.8", optional = true }
num-traits = { workspace = true, optional = true }
serde = { workspace = true, optional = true }

dialoguer = { version = "0.11", default-features = false, features = ["editor", "completion"], optional = true }
console = { version = "0.15", optional = true }
ctrlc = { version = "3.4", optional = true }

[dev-dependencies]
goldenfile = "1.1.0"
Expand All @@ -47,7 +49,8 @@ rand.workspace = true
[features]
configs = ["serde_dhall"]
random = ["configs", "arbitrary", "fake", "rand", "num-traits", "serde"]
all = ["random"]
assist = ["dep:dialoguer", "dep:console", "dep:ctrlc"]
all = ["random", "assist"]

# docs.rs-specific configuration
# To test locally: RUSTDOCFLAGS="--cfg docsrs" cargo +nightly doc --features all
Expand Down

0 comments on commit a6cc9e6

Please sign in to comment.