add version to interfaces

This commit is contained in:
vms 2021-03-15 12:37:15 +03:00
parent f6fdc50e75
commit 5758fa66c6
8 changed files with 133 additions and 18 deletions

38
Cargo.lock generated
View File

@ -1,5 +1,7 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "arrayvec"
version = "0.5.2"
@ -83,6 +85,15 @@ dependencies = [
"version_check",
]
[[package]]
name = "pest"
version = "2.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "10f4872ae94d7b90ae48754df22fd42ad52ce740b8f370b03da4835417403e53"
dependencies = [
"ucd-trie",
]
[[package]]
name = "proc-macro2"
version = "1.0.24"
@ -113,6 +124,24 @@ version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "50b8b2cd387f744f69469aaed197954ba4c0ecdb31e02edf99b023e0df11178a"
[[package]]
name = "semver"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6"
dependencies = [
"semver-parser",
]
[[package]]
name = "semver-parser"
version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "00b0bef5b7f9e0df16536d3961cfb6e84331c065b4066afb39768d0e319411f7"
dependencies = [
"pest",
]
[[package]]
name = "serde"
version = "1.0.118"
@ -161,6 +190,12 @@ dependencies = [
"unicode-xid",
]
[[package]]
name = "ucd-trie"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c"
[[package]]
name = "unicode-xid"
version = "0.2.1"
@ -175,13 +210,14 @@ checksum = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed"
[[package]]
name = "wasmer-interface-types-fl"
version = "0.17.24"
version = "0.17.25"
dependencies = [
"fluence-it-types",
"it-to-bytes",
"log",
"nom",
"safe-transmute",
"semver",
"serde",
"serde_json",
"wast",

View File

@ -72,13 +72,7 @@ where
W: Write,
{
fn to_bytes(&self, writer: &mut W) -> io::Result<()> {
// Size first.
writer.write_all(&[self.len() as u8])?;
// Then the string.
writer.write_all(self.as_bytes())?;
Ok(())
self.as_str().to_bytes(writer)
}
}

View File

@ -1,6 +1,6 @@
[package]
name = "wasmer-interface-types-fl"
version = "0.17.24"
version = "0.17.25"
description = "WebAssembly Interface Types library for Wasmer"
license = "MIT"
authors = ["The Wasmer Engineering Team <engineering@wasmer.io>"]
@ -22,5 +22,7 @@ serde_json = "1.0"
safe-transmute = "0.11.0"
log = "0.4.11"
semver = "0.11.0"
[features]
default = ["serde"]

View File

@ -98,6 +98,9 @@ pub struct Implementation {
/// Represents the kind of interface.
#[derive(PartialEq, Eq, Debug, Clone, Hash, Serialize, Deserialize)]
pub enum InterfaceKind {
/// A version.
Version,
/// A type.
Type,
@ -116,8 +119,11 @@ pub enum InterfaceKind {
/// Represents a set of interfaces, i.e. it entirely describes a WIT
/// definition.
#[derive(PartialEq, Eq, Debug, Default, Clone, Hash)]
#[derive(PartialEq, Eq, Debug, Clone, Hash)]
pub struct Interfaces<'input> {
/// Version of IT.
pub version: semver::Version,
/// All the types.
pub types: Vec<Type>,

View File

@ -35,6 +35,7 @@ impl TryFrom<u8> for InterfaceKind {
0x02 => Self::Adapter,
0x03 => Self::Export,
0x04 => Self::Implementation,
0x05 => Self::Version,
_ => return Err("Unknown interface kind code."),
})
}
@ -487,6 +488,7 @@ fn interfaces<'input, E: ParseError<&'input [u8]>>(
) -> IResult<&'input [u8], Interfaces, E> {
let mut input = bytes;
let mut all_versions = vec![];
let mut all_types = vec![];
let mut all_imports = vec![];
let mut all_adapters = vec![];
@ -500,6 +502,10 @@ fn interfaces<'input, E: ParseError<&'input [u8]>>(
.map_err(|_| Err::Error(make_error(input, ErrorKind::ParseTo)))?;
match interface_kind {
InterfaceKind::Version => {
consume!((input, new_version) = string(input)?);
all_versions.push(new_version);
}
InterfaceKind::Type => {
consume!((input, mut new_types) = types(input)?);
all_types.append(&mut new_types);
@ -527,9 +533,12 @@ fn interfaces<'input, E: ParseError<&'input [u8]>>(
}
}
let version = try_into_version(all_versions).map_err(|e| Err::Error(make_error(input, e)))?;
Ok((
input,
Interfaces {
version,
types: all_types,
imports: all_imports,
adapters: all_adapters,
@ -539,6 +548,22 @@ fn interfaces<'input, E: ParseError<&'input [u8]>>(
))
}
fn try_into_version(versions: Vec<&str>) -> Result<semver::Version, ErrorKind> {
use std::str::FromStr;
if versions.is_empty() {
return Err(ErrorKind::NoneOf);
}
if versions.len() != 1 {
return Err(ErrorKind::Many0);
}
let version = semver::Version::from_str(&versions[0]).map_err(|_| ErrorKind::IsNot)?;
Ok(version)
}
/// Parse a sequence of bytes, expecting it to be a valid WIT binary
/// representation, into an [`Interfaces`](crate::ast::Interfaces)
/// structure.

View File

@ -18,6 +18,7 @@ mod keyword {
custom_keyword!(r#type = "type");
custom_keyword!(record);
custom_keyword!(field);
custom_keyword!(version);
// Special symbols
custom_keyword!(comma = ",");
@ -380,6 +381,7 @@ impl Parse<'_> for FunctionType {
#[derive(PartialEq, Debug)]
enum Interface<'a> {
Version(String),
Type(Type),
Import(Import<'a>),
Adapter(Adapter),
@ -397,7 +399,9 @@ impl<'a> Parse<'a> for Interface<'a> {
let mut lookahead = parser.lookahead1();
if lookahead.peek::<keyword::r#type>() {
if lookahead.peek::<keyword::version>() {
Ok(Interface::Version(parser.parse()?))
} else if lookahead.peek::<keyword::r#type>() {
Ok(Interface::Type(parser.parse()?))
} else if lookahead.peek::<keyword::import>() {
Ok(Interface::Import(parser.parse()?))
@ -548,26 +552,66 @@ impl<'a> Parse<'a> for Adapter {
impl<'a> Parse<'a> for Interfaces<'a> {
fn parse(parser: Parser<'a>) -> Result<Self> {
let mut interfaces: Interfaces = Default::default();
let mut version: Option<semver::Version> = None;
let mut types = vec![];
let mut imports = vec![];
let mut adapters = vec![];
let mut exports = vec![];
let mut implementations = vec![];
while !parser.is_empty() {
let interface = parser.parse::<Interface>()?;
match interface {
Interface::Type(ty) => interfaces.types.push(ty),
Interface::Import(import) => interfaces.imports.push(import),
Interface::Adapter(adapter) => interfaces.adapters.push(adapter),
Interface::Export(export) => interfaces.exports.push(export),
Interface::Implementation(implementation) => {
interfaces.implementations.push(implementation)
Interface::Version(version_str) => {
try_handle_version(&version_str, &mut version, &parser)?
}
Interface::Type(ty) => types.push(ty),
Interface::Import(import) => imports.push(import),
Interface::Adapter(adapter) => adapters.push(adapter),
Interface::Export(export) => exports.push(export),
Interface::Implementation(implementation) => implementations.push(implementation),
}
}
let version = version.ok_or_else(|| {
wast::Error::new(parser.cur_span(), String::from("version must be specified"))
})?;
let interfaces = Interfaces {
version,
types,
imports,
adapters,
exports,
implementations,
};
Ok(interfaces)
}
}
fn try_handle_version(
version_str: &str,
version: &mut Option<semver::Version>,
parser: &Parser<'_>,
) -> Result<()> {
use std::str::FromStr;
if version.is_some() {
return Err(wast::Error::new(
parser.cur_span(),
String::from("only one version directive is possible"),
));
}
let parsed_version = semver::Version::from_str(version_str)
.map_err(|e| wast::Error::new(parser.cur_span(), format!("version is corrupted: {}", e)))?;
*version = Some(parsed_version);
Ok(())
}
/// Parse a WIT definition in its textual format, and produces an
/// [AST](crate::ast) with the [`Interfaces`](crate::ast::Interfaces)
/// structure upon succesful.

View File

@ -33,6 +33,7 @@ where
Self::Adapter => 0x02_u8.to_bytes(writer),
Self::Export => 0x03_u8.to_bytes(writer),
Self::Implementation => 0x04_u8.to_bytes(writer),
Self::Version => 0x05_u8.to_bytes(writer),
}
}
}
@ -144,6 +145,9 @@ where
W: Write,
{
fn to_bytes(&self, writer: &mut W) -> io::Result<()> {
InterfaceKind::Version.to_bytes(writer)?;
self.version.to_string().to_bytes(writer)?;
if !self.types.is_empty() {
InterfaceKind::Type.to_bytes(writer)?;
self.types.to_bytes(writer)?;

View File

@ -296,6 +296,10 @@ impl<'input> ToString for &Interfaces<'input> {
}
};
output.push_str("Version: ");
output.push_str(&self.version.to_string());
separator(&mut output);
if !types.is_empty() {
output.push_str(";; Types");
output.push_str(&types);