Trait Interface
pub trait Interface<Input, Output> {
// Required method
fn call(input: Input) -> Output;
}Expand description
An Interface specifies the behavior of a system as a map from input to
output.
It is easy to think of an interface as a function. But it is far more
general and can represent a function, a network call, an event, a process,
an event or a complete system. The essence of Interface is captured by
the call method.
fn call(input: I) -> O;§A Few Examples
§A Function as Interface
TBD
§A Type implementing Interface
A simple increment interface. This is not very interesting, but just
to start building familiarity with Interfaces.
use metals_poly::interface::Interface;
/// The types that will implement the necessary increment behavior
struct Increment;
/// Increment represents a computation that turns i32 into some other i32.
impl Interface<i32, i32> for Increment {
/// Increment the input by 1.
fn call(input: i32) -> i32 {
input + 1
}
}
assert_eq!(Increment::call(1), 2);There are no self (read it as no state) or multiple arguments or
anything interesting here at all. Looks very boring, to be honest. While
it may not appear terribly exciting, let us build a few more interfaces
for Increment.
struct Increment;
// x-- hiding previous lines for brevity
// Increment interface for u32 -> u32
impl Interface<u32, u32> for Increment {
fn call(input: u32) -> u32 {
input + 1
}
}
// We have to tell the input type
assert_eq!(Increment::call(1u32), 2u32);
// This calls previous i32 -> i32
assert_eq!(Increment::call(1), 2);But if we add another interface say, say to increment by 10, for same input and output types, we get compiler error.
struct Increment;
impl Interface<i32, i32> for Increment {
fn call(input: i32) -> i32 {
input + 1
}
}
// This will lead to compiler error for reimplementing the same function
impl Interface<i32, i32> for Increment {
fn call(input: i32) -> i32 {
input + 10
}
}But we can mix input and output types. For e.g., we can have the same increment by 1 method defined for i32 -> u32 (or vice versa).
struct Increment;
// x-- hiding previous code lines for brevity
// Increment interface for i32 -> i32
impl Interface<i32, i32> for Increment {
// x-- snip implementation code
}
// Increment interface for u32 -> u32
impl Interface<u32, u32> for Increment {
// x-- snip implementation code
}
// Increment interface for i32 -> u32
impl Interface<i32, u32> for Increment {
fn call(input: i32) -> u32 {
// x-- snip implementation code
u32::try_from(input).unwrap() + 1u32
}
}
// Now we have to provide a lot of type information to both at calling
// and at assert
// Calling i32 -> i32. Needs type info even for i32 -> i32
let o: i32 = Increment::call(1i32);
assert_eq!(o, 2i32);
// Calling i32 -> u32
let o: u32 = Increment::call(1i32);
assert_eq!(o, 2u32);
// Calling u32 -> u32, not different from last time
assert_eq!(Increment::call(1u32), 2u32);Required Methods§
Dyn Compatibility§
This trait is not dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.