Skip to content
This repository was archived by the owner on Mar 29, 2022. It is now read-only.

Re-add Option and Result. #68

Merged
merged 17 commits into from
Mar 26, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions src/chain/auth.sw
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ library auth;

use ::address::Address;
use ::contract_id::ContractId;
use ::result::Result;

pub enum AuthError {
ContextError: (),
Expand All @@ -23,19 +24,18 @@ pub fn caller_is_external() -> bool {
}

/// Get the `Sender` (ie: `Address`| ContractId) from which a call was made.
/// TODO: Return a Result::Ok(Sender) or Result::Error.
pub fn msg_sender() -> b256 {
/// Returns a Result::Ok(Sender) or Result::Error.
// NOTE: Currently only returns Result::Ok variant if the parent context is Internal.
pub fn msg_sender() -> Result<Sender, AuthError> {
if caller_is_external() {
// TODO: Add call to get_coins_owner() here when implemented,
// Result::Err(AuthError::ContextError)
0x0000000000000000000000000000000000000000000000000000000000000000
Result::Err(AuthError::ContextError)
} else {
// Get caller's contract ID
let id = ~ContractId::from(asm(r1) {
gm r1 i2;
r1: b256
});
// Result::Ok(Sender::Id(id))
id.value
Result::Ok(Sender::Id(id))
}
}
2 changes: 2 additions & 0 deletions src/lib.sw
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
library std;

dep option;
dep result;
dep constants;
dep contract_id;
dep context;
Expand Down
45 changes: 45 additions & 0 deletions src/option.sw
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
//! Error handling with the `Option` type.
//!
//! [`Option<T>`][`Option`] is the type used for representing the existence or absence of a value. It is an enum with the variants, [`Some(T)`], representing
//! some value, and [`None()`], representing
//! no value.

library option;

/// `Option` is a type that represents either the existence of a value ([`Some`]) or a value's absence
/// ([`None`]).
pub enum Option<T> {
/// Contains the value
Some: T,

/// Signifies the absence of a value
None: (),
}

/////////////////////////////////////////////////////////////////////////////
// Type implementation
/////////////////////////////////////////////////////////////////////////////

impl<T> Option<T> {
/////////////////////////////////////////////////////////////////////////
// Querying the contained values
/////////////////////////////////////////////////////////////////////////

/// Returns `true` if the result is [`Some`].
fn is_some(self) -> bool {
if let Option::Some(t) = self {
true
} else {
false
}
}

/// Returns `true` if the result is [`None`].
fn is_none(self) -> bool {
if let Option::Some(t) = self {
false
} else {
true
}
}
}
46 changes: 46 additions & 0 deletions src/result.sw
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
//! Error handling with the `Result` type.
//!
//! [`Result<T, E>`][`Result`] is the type used for returning and propagating
//! errors. It is an enum with the variants, [`Ok(T)`], representing
//! success and containing a value, and [`Err(E)`], representing error
//! and containing an error value.

library result;

/// `Result` is a type that represents either success ([`Ok`]) or failure
/// ([`Err`]).
pub enum Result<T, E> {
/// Contains the success value
Ok: T,

/// Contains the error value
Err: E,
}

/////////////////////////////////////////////////////////////////////////////
// Type implementation
/////////////////////////////////////////////////////////////////////////////

impl<T, E> Result<T, E> {
/////////////////////////////////////////////////////////////////////////
// Querying the contained values
/////////////////////////////////////////////////////////////////////////

/// Returns `true` if the result is [`Ok`].
fn is_ok(self) -> bool {
if let Result::Ok(t) = self {
true
} else {
false
}
}

/// Returns `true` if the result is [`Err`].
fn is_err(self) -> bool {
if let Result::Ok(t) = self {
false
} else {
true
}
}
}
2 changes: 2 additions & 0 deletions tests/test_projects/harness.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
// Add test modules here:
mod call_frames;
mod contract_id_type;
mod option;
mod registers;
mod result;
mod token_ops;
8 changes: 8 additions & 0 deletions tests/test_projects/option/Forc.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[project]
authors = ["Fuel Labs <contact@fuel.sh>"]
entry = "main.sw"
license = "Apache-2.0"
name = "option"

[dependencies]
std = { path = "../../../" }
32 changes: 32 additions & 0 deletions tests/test_projects/option/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
use fuel_core::service::Config;
use fuel_tx::{consts::MAX_GAS_PER_TX, Receipt, Transaction};
use fuels_contract::script::Script;
use fuels_signers::provider::Provider;

#[tokio::test]
async fn run_valid() {
let bin = std::fs::read("test_projects/option/out/debug/option.bin");
let client = Provider::launch(Config::local_node()).await.unwrap();

let tx = Transaction::Script {
gas_price: 0,
gas_limit: MAX_GAS_PER_TX,
maturity: 0,
byte_price: 0,
receipts_root: Default::default(),
script: bin.unwrap(), // Here we pass the compiled script into the transaction
script_data: vec![],
inputs: vec![],
outputs: vec![],
witnesses: vec![vec![].into()],
metadata: None,
};

let script = Script::new(tx);
let receipts = script.call(&client).await.unwrap();

if let Receipt::Return { .. } = receipts[0] {
} else {
assert!(false);
}
}
25 changes: 25 additions & 0 deletions tests/test_projects/option/src/main.sw
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
script;

use std::chain::panic;
use std::option::*;

fn main() {
test_some();
test_none();
}

fn test_some() {
let o = Option::Some(42u64);

if (!o.is_some() || o.is_none()) {
panic(0);
}
}

fn test_none() {
let o = Option::None::<()>();

if (o.is_some() || !o.is_none()) {
panic(0);
}
}
8 changes: 8 additions & 0 deletions tests/test_projects/result/Forc.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[project]
authors = ["Fuel Labs <contact@fuel.sh>"]
entry = "main.sw"
license = "Apache-2.0"
name = "result"

[dependencies]
std = { path = "../../../" }
32 changes: 32 additions & 0 deletions tests/test_projects/result/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
use fuel_core::service::Config;
use fuel_tx::{consts::MAX_GAS_PER_TX, Receipt, Transaction};
use fuels_contract::script::Script;
use fuels_signers::provider::Provider;

#[tokio::test]
async fn run_valid() {
let bin = std::fs::read("test_projects/result/out/debug/result.bin");
let client = Provider::launch(Config::local_node()).await.unwrap();

let tx = Transaction::Script {
gas_price: 0,
gas_limit: MAX_GAS_PER_TX,
maturity: 0,
byte_price: 0,
receipts_root: Default::default(),
script: bin.unwrap(), // Here we pass the compiled script into the transaction
script_data: vec![],
inputs: vec![],
outputs: vec![],
witnesses: vec![vec![].into()],
metadata: None,
};

let script = Script::new(tx);
let receipts = script.call(&client).await.unwrap();

if let Receipt::Return { .. } = receipts[0] {
} else {
assert!(false);
}
}
25 changes: 25 additions & 0 deletions tests/test_projects/result/src/main.sw
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
script;

use std::chain::panic;
use std::result::*;

fn main() {
test_ok();
test_err();
}

fn test_ok() {
let r = Result::Ok::<u64, ()>(42u64);

if (!r.is_ok() || r.is_err()) {
panic(0);
}
}

fn test_err() {
let r = Result::Err::<(), ()>(());

if (r.is_ok() || !r.is_err()) {
panic(0);
}
}