Skip to content

Commit

Permalink
Implement Witty traits for log::Level (#1877)
Browse files Browse the repository at this point in the history
* Add a `log` feature to `linera-witty`

Prepare to implement the Witty traits for a type from the `log` crate,
but only if requested by the user.

* Implement Witty traits for `log::Level`

Place it behind a feature gate, so that the `log` dependency is only
included if requested.

* Test WIT roundtrip of `log::Level`

Ensure all variants can be stored in memory and loaded from memory
following the WIT specification, as well as lowered into and lifted from
its flat layout.
  • Loading branch information
jvff authored Apr 6, 2024
1 parent 1c1dbd8 commit bb40c47
Show file tree
Hide file tree
Showing 6 changed files with 134 additions and 0 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

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

2 changes: 2 additions & 0 deletions linera-witty/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ edition = "2021"

[features]
default = ["macros"]
log = ["dep:log"]
macros = ["linera-witty-macros"]
test = ["linera-witty-macros?/test"]
wasmer = ["dep:wasmer", "linera-witty-macros?/wasmer", "wasmer-vm"]
Expand All @@ -22,6 +23,7 @@ anyhow.workspace = true
either.workspace = true
frunk.workspace = true
linera-witty-macros = { workspace = true, optional = true }
log = { workspace = true, optional = true }
thiserror.workspace = true
wasmer = { workspace = true, optional = true }
wasmer-vm = { workspace = true, optional = true }
Expand Down
1 change: 1 addition & 0 deletions linera-witty/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

fn main() {
cfg_aliases::cfg_aliases! {
with_log: { feature = "log" },
with_testing: { any(test, feature = "test") },
with_wasmer: { feature = "wasmer" },
with_wasmtime: { feature = "wasmtime" },
Expand Down
117 changes: 117 additions & 0 deletions linera-witty/src/type_traits/implementations/log.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
// Copyright (c) Zefchain Labs, Inc.
// SPDX-License-Identifier: Apache-2.0

//! Implementations of the custom traits for types from the [`log`] crate.
use std::borrow::Cow;

use frunk::{hlist_pat, HList};
use log::Level;

use crate::{
GuestPointer, InstanceWithMemory, Layout, Memory, Runtime, RuntimeError, RuntimeMemory,
WitLoad, WitStore, WitType,
};

impl WitType for Level {
const SIZE: u32 = 1;

type Layout = HList![i8];
type Dependencies = HList![];

fn wit_type_name() -> Cow<'static, str> {
"log-level".into()
}

fn wit_type_declaration() -> Cow<'static, str> {
concat!(
" enum log-level {\n",
" error,\n",
" warn,\n",
" info,\n",
" debug,\n",
" trace,\n",
" }\n",
)
.into()
}
}

impl WitLoad for Level {
fn load<Instance>(
memory: &Memory<'_, Instance>,
location: GuestPointer,
) -> Result<Self, RuntimeError>
where
Instance: InstanceWithMemory,
<Instance::Runtime as Runtime>::Memory: RuntimeMemory<Instance>,
{
match u8::load(memory, location)? {
0 => Ok(Level::Error),
1 => Ok(Level::Warn),
2 => Ok(Level::Info),
3 => Ok(Level::Debug),
4 => Ok(Level::Trace),
_ => unreachable!("Invalid log level"),
}
}

fn lift_from<Instance>(
hlist_pat![discriminant]: <Self::Layout as Layout>::Flat,
_memory: &Memory<'_, Instance>,
) -> Result<Self, RuntimeError>
where
Instance: InstanceWithMemory,
<Instance::Runtime as Runtime>::Memory: RuntimeMemory<Instance>,
{
match discriminant {
0 => Ok(Level::Error),
1 => Ok(Level::Warn),
2 => Ok(Level::Info),
3 => Ok(Level::Debug),
4 => Ok(Level::Trace),
_ => unreachable!("Invalid log level"),
}
}
}

impl WitStore for Level {
fn store<Instance>(
&self,
memory: &mut Memory<'_, Instance>,
location: GuestPointer,
) -> Result<(), RuntimeError>
where
Instance: InstanceWithMemory,
<Instance::Runtime as Runtime>::Memory: RuntimeMemory<Instance>,
{
let discriminant: i8 = match self {
Level::Error => 0,
Level::Warn => 1,
Level::Info => 2,
Level::Debug => 3,
Level::Trace => 4,
};

discriminant.store(memory, location)
}

fn lower<Instance>(
&self,
memory: &mut Memory<'_, Instance>,
) -> Result<<Self::Layout as Layout>::Flat, RuntimeError>
where
Instance: InstanceWithMemory,
<Instance::Runtime as Runtime>::Memory: RuntimeMemory<Instance>,
{
let discriminant: i8 = match self {
Level::Error => 0,
Level::Warn => 1,
Level::Info => 2,
Level::Debug => 3,
Level::Trace => 4,
};

discriminant.lower(memory)
}
}
2 changes: 2 additions & 0 deletions linera-witty/src/type_traits/implementations/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
mod custom_types;
mod frunk;
#[cfg(with_log)]
mod log;
mod std;
#[cfg(test)]
mod tests;
11 changes: 11 additions & 0 deletions linera-witty/src/type_traits/implementations/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,17 @@ fn btree_map() {
);
}

/// Test roundtrip of [`log::Level`].
#[cfg(with_log)]
#[test]
fn log_level() {
use log::Level::*;
for (index, level) in [Error, Warn, Info, Debug, Trace].into_iter().enumerate() {
test_memory_roundtrip(&level, &[index as u8], &[]);
test_flattening_roundtrip(&level, hlist![index as i32], &[]);
}
}

/// Test storing an instance of `T` to memory, checking that the `layout_data` bytes followed by
/// the `heap_data` bytes are correctly written, and check that the instance can be loaded from
/// those bytes.
Expand Down

0 comments on commit bb40c47

Please sign in to comment.