mooncoap

    Bounded, deterministic unicast CoAP protocol core for MoonBit

    coap
    rfc7252
    network
    protocol
    iot
    Download zip
    Version
    0.1.1
    License
    Apache-2.0
    Last updated
    10 hours ago
    Downloads
    4

    Dependencies

    #MoonCoAP

    Reusable unicast CoAP protocol library implemented in MoonBit.

    The pure core provides RFC7252 message and option codecs, client/server exchange state machines, bounded duplicate suppression, resource routing, conditional representations, response caching and RFC6690 discovery. The native udp package uses the public moonbitlang/async socket API.

    See the repository README for installation, four runnable examples, API usage and reproducible validation. The protocol support matrix defines the implemented subset. DTLS, OSCORE, Observe, Blockwise, multicast, proxying and TCP are outside this release. IPv6 UDP has not been validated.

    Licensed under Apache-2.0. Standards and dependency provenance are documented in THIRD_PARTY.md.

    Action

    pub(all) enum Action {
    SendDatagram(String, Bytes)
    RequestReceived(IncomingRequest)
    ResponseReceived(Int, Message)
    Failed(Int, Failure)
    Cancelled(Int)
    } derive(Eq,
    Debug
    )

    Action::equal

    fn Action::equal(Action, Action) -> Bool

    Action::not_equal

    fn Action::not_equal(x : Action, y : Action) -> Bool

    Action::to_repr

    Allocator

    pub struct Allocator {
    // private fields
    }

    Allocator::active_leases

    fn Allocator::active_leases(self : Allocator) -> Int

    Allocator::allocate_mid

    fn Allocator::allocate_mid(self : Allocator, peer : String, now : Int64) -> Result[Int, Failure]

    Allocator::allocate_token

    fn Allocator::allocate_token(self : Allocator) -> Result[Bytes, Failure]

    Allocator::collect

    fn Allocator::collect(self : Allocator, now : Int64) -> Result[Int, Failure]

    Allocator::is_reserved

    fn Allocator::is_reserved(self : Allocator, peer : String, mid : Int) -> Bool

    Allocator::new

    fn Allocator::new(config : Config) -> Result[Allocator, Failure]

    Allocator::next_expiry

    fn Allocator::next_expiry(self : Allocator) -> Int64?

    Allocator::remaining_capacity

    fn Allocator::remaining_capacity(self : Allocator) -> Int

    Allocator::reserve

    fn Allocator::reserve(self : Allocator, peer : String, mid : Int, now : Int64) -> Result[Unit, Failure]

    CacheKey

    pub(all) struct CacheKey {
    peer : String
    options : Array[CoapOption]
    } derive(Eq,
    Debug
    )

    CacheKey::equal

    fn CacheKey::equal(CacheKey, CacheKey) -> Bool

    CacheKey::not_equal

    fn CacheKey::not_equal(x : CacheKey, y : CacheKey) -> Bool

    CacheKey::to_repr

    CacheLookup

    pub(all) enum CacheLookup {
    Miss
    Fresh(Response)
    Stale(Response, Request)
    } derive(Eq,
    Debug
    )

    CacheLookup::equal

    fn CacheLookup::equal(CacheLookup, CacheLookup) -> Bool

    CacheLookup::not_equal

    fn CacheLookup::not_equal(x : CacheLookup, y : CacheLookup) -> Bool

    CacheStats

    pub(all) struct CacheStats {
    hits : Int64
    misses : Int64
    stale : Int64
    insertions : Int64
    validations : Int64
    evictions : Int64
    entries : Int
    bytes : Int
    } derive(Eq,
    Debug
    )

    CacheStats::equal

    fn CacheStats::equal(CacheStats, CacheStats) -> Bool

    CacheStats::not_equal

    fn CacheStats::not_equal(x : CacheStats, y : CacheStats) -> Bool

    CoapOption

    pub(all) struct CoapOption {
    number : Int
    value : Bytes
    } derive(Eq,
    Debug
    )

    CoapOption::equal

    fn CoapOption::equal(CoapOption, CoapOption) -> Bool

    CoapOption::not_equal

    fn CoapOption::not_equal(x : CoapOption, y : CoapOption) -> Bool

    CoapUri

    pub(all) struct CoapUri {
    host : String
    port : Int
    path : Array[Bytes]
    query : Array[Bytes]
    } derive(Eq,
    Debug
    )

    CoapUri::equal

    fn CoapUri::equal(CoapUri, CoapUri) -> Bool

    CoapUri::not_equal

    fn CoapUri::not_equal(x : CoapUri, y : CoapUri) -> Bool

    CoapUri::parse

    fn CoapUri::parse(text : String, limits : Limits) -> Result[CoapUri, Failure]

    CoapUri::to_options

    fn CoapUri::to_options(self : CoapUri) -> Array[CoapOption]

    CoapUri::to_repr

    CoapUri::to_string

    fn CoapUri::to_string(self : CoapUri) -> String

    Code

    pub(all) struct Code {
    value : Int
    } derive(Eq,
    Debug
    )

    Code::class

    fn Code::class(self : Code) -> Int

    Code::description

    fn Code::description(self : Code) -> String

    Code::detail

    fn Code::detail(self : Code) -> Int

    Code::equal

    fn Code::equal(Code, Code) -> Bool

    Code::is_request

    fn Code::is_request(self : Code) -> Bool

    Code::is_response

    fn Code::is_response(self : Code) -> Bool

    Code::is_success

    fn Code::is_success(self : Code) -> Bool

    Code::not_equal

    fn Code::not_equal(x : Code, y : Code) -> Bool

    Code::request

    fn Code::request(verb : Method) -> Code

    Code::response

    fn Code::response(class : Int, detail : Int) -> Result[Code, Failure]

    Code::to_repr

    Code::verb

    fn Code::verb(self : Code) -> Method?

    Config

    pub(all) struct Config {
    limits : Limits
    ack_timeout_ms : Int64
    ack_random_factor_permille : Int
    max_retransmit : Int
    exchange_lifetime_ms : Int64
    non_lifetime_ms : Int64
    response_timeout_ms : Int64
    max_peers : Int
    max_exchanges : Int
    max_dedup : Int
    max_mid_leases : Int
    max_queue : Int
    max_actions : Int
    nstart : Int
    initial_mid : Int
    token_seed : Int64
    } derive(Eq,
    Debug
    )

    Config::default

    fn Config::default() -> Config

    Config::equal

    fn Config::equal(Config, Config) -> Bool

    Config::max_transmit_span

    fn Config::max_transmit_span(self : Config) -> Int64

    Config::not_equal

    fn Config::not_equal(x : Config, y : Config) -> Bool

    Config::to_repr

    Config::validate

    fn Config::validate(self : Config) -> Result[Unit, Failure]

    pub(all) struct CoreLink {
    target : String
    attributes : Array[LinkAttribute]
    } derive(Eq,
    Debug
    )

    CoreLink::attribute

    fn CoreLink::attribute(self : CoreLink, name : String) -> String?

    CoreLink::equal

    fn CoreLink::equal(CoreLink, CoreLink) -> Bool

    CoreLink::not_equal

    fn CoreLink::not_equal(x : CoreLink, y : CoreLink) -> Bool

    CoreLink::to_repr

    CoreLink::validate

    fn CoreLink::validate(self : CoreLink, limits : Limits) -> Result[Unit, Failure]

    Discovery

    pub struct Discovery {
    // private fields
    }

    Discovery::add

    fn Discovery::add(self : Discovery, link : CoreLink) -> Result[Unit, Failure]

    Discovery::handle

    fn Discovery::handle(self : Discovery, message : Message) -> Response

    fn Discovery::links(self : Discovery) -> Array[CoreLink]

    Discovery::new

    fn Discovery::new(limits : Limits) -> Result[Discovery, Failure]

    Discovery::remove

    fn Discovery::remove(self : Discovery, target : String) -> Bool

    Endpoint

    pub struct Endpoint {
    // private fields
    }

    Endpoint::acknowledge

    fn Endpoint::acknowledge(self : Endpoint, id : Int, now : Int64) -> Result[Unit, Failure]

    Endpoint::action_capacity

    fn Endpoint::action_capacity(self : Endpoint) -> Int

    Endpoint::active_for_peer

    fn Endpoint::active_for_peer(self : Endpoint, peer : String) -> Int

    Endpoint::active_peers

    fn Endpoint::active_peers(self : Endpoint) -> Array[String]

    Endpoint::cancel

    fn Endpoint::cancel(self : Endpoint, id : Int, now : Int64) -> Result[Unit, Failure]

    Endpoint::drain

    fn Endpoint::drain(self : Endpoint) -> Array[Action]

    Endpoint::exchange_count

    fn Endpoint::exchange_count(self : Endpoint) -> Int

    Endpoint::exchanges

    fn Endpoint::exchanges(self : Endpoint) -> Array[ExchangeView]

    Endpoint::new

    fn Endpoint::new(config : Config) -> Result[Endpoint, Failure]

    Endpoint::next_deadline

    fn Endpoint::next_deadline(self : Endpoint) -> Int64?

    Endpoint::pending_actions

    fn Endpoint::pending_actions(self : Endpoint) -> Int

    Endpoint::poll

    fn Endpoint::poll(self : Endpoint, now : Int64) -> Result[Unit, Failure]

    Endpoint::queued_count

    fn Endpoint::queued_count(self : Endpoint) -> Int

    Endpoint::receive

    fn Endpoint::receive(self : Endpoint, peer : String, packet : Bytes, now : Int64) -> Result[Unit, Failure]

    Endpoint::receive_request

    fn Endpoint::receive_request(self : Endpoint, peer : String, packet : Bytes, now : Int64) -> Result[Unit, Failure]

    Endpoint::receive_response

    fn Endpoint::receive_response(self : Endpoint, peer : String, packet : Bytes, now : Int64) -> Result[Unit, Failure]

    Endpoint::request

    fn Endpoint::request(self : Endpoint, peer : String, request : Request, now : Int64, random_sample : Int) -> Result[Int, Failure]

    Endpoint::respond

    fn Endpoint::respond(self : Endpoint, id : Int, response : Response, now : Int64, random_sample : Int) -> Result[Unit, Failure]

    Endpoint::response_receipt_count

    fn Endpoint::response_receipt_count(self : Endpoint) -> Int

    Endpoint::serve

    fn Endpoint::serve(self : Endpoint, router : Router, incoming : IncomingRequest, now : Int64) -> Result[Unit, Failure]

    Endpoint::server_records

    fn Endpoint::server_records(self : Endpoint) -> Array[ServerView]

    ExchangePhase

    pub(all) enum ExchangePhase {
    Queued
    Sending
    WaitingResponse
    Finished
    } derive(Eq,
    Debug
    )

    ExchangePhase::equal

    ExchangePhase::not_equal

    fn ExchangePhase::not_equal(x : ExchangePhase, y : ExchangePhase) -> Bool

    ExchangeView

    pub(all) struct ExchangeView {
    id : Int
    peer : String
    mid : Int
    token : Bytes
    phase : ExchangePhase
    created_at : Int64
    last_sent_at : Int64
    deadline : Int64
    transmit_deadline : Int64
    next_retry : Int64?
    interval : Int64
    retransmissions : Int
    } derive(Eq,
    Debug
    )

    ExchangeView::equal

    ExchangeView::not_equal

    fn ExchangeView::not_equal(x : ExchangeView, y : ExchangeView) -> Bool

    Failure

    pub(all) enum Failure {
    Syntax(Int, String)
    Invalid(String)
    Capacity(String)
    Unsupported(String)
    Clock(String)
    NotFound(String)
    Conflict(String)
    Transport(String)
    TimedOut
    ResetByPeer
    } derive(Eq,
    Debug
    )

    Failure::equal

    fn Failure::equal(Failure, Failure) -> Bool

    Failure::not_equal

    fn Failure::not_equal(x : Failure, y : Failure) -> Bool

    Failure::to_repr

    IncomingRequest

    pub(all) struct IncomingRequest {
    id : Int
    peer : String
    message : Message
    received_at : Int64
    } derive(Eq,
    Debug
    )

    IncomingRequest::equal

    IncomingRequest::not_equal

    fn IncomingRequest::not_equal(x : IncomingRequest, y : IncomingRequest) -> Bool

    Limits

    pub(all) struct Limits {
    max_datagram : Int
    max_options : Int
    max_option_bytes : Int
    max_payload : Int
    max_uri_bytes : Int
    max_links : Int
    max_link_attributes : Int
    } derive(Eq,
    Debug
    )

    Limits::default

    fn Limits::default() -> Limits

    Limits::equal

    fn Limits::equal(Limits, Limits) -> Bool

    Limits::not_equal

    fn Limits::not_equal(x : Limits, y : Limits) -> Bool

    Limits::to_repr

    Limits::validate

    fn Limits::validate(self : Limits) -> Result[Unit, Failure]

    LinkAttribute

    pub(all) struct LinkAttribute {
    name : String
    value : String?
    } derive(Eq,
    Debug
    )

    LinkAttribute::equal

    LinkAttribute::not_equal

    fn LinkAttribute::not_equal(x : LinkAttribute, y : LinkAttribute) -> Bool

    LinkFilter

    pub(all) struct LinkFilter {
    name : String
    value : String
    prefix : Bool
    } derive(Eq,
    Debug
    )

    LinkFilter::equal

    fn LinkFilter::equal(LinkFilter, LinkFilter) -> Bool

    LinkFilter::matches

    fn LinkFilter::matches(self : LinkFilter, link : CoreLink) -> Bool

    LinkFilter::not_equal

    fn LinkFilter::not_equal(x : LinkFilter, y : LinkFilter) -> Bool

    LinkFilter::parse

    fn LinkFilter::parse(query : String) -> Result[LinkFilter, Failure]

    Message

    pub(all) struct Message {
    msg_type : MessageType
    code : Code
    mid : Int
    token : Bytes
    options : Array[CoapOption]
    payload : Bytes
    } derive(Eq,
    Debug
    )

    Message::copy

    fn Message::copy(self : Message) -> Message

    Message::equal

    fn Message::equal(Message, Message) -> Bool

    Message::first_option

    fn Message::first_option(self : Message, number : Int) -> Bytes?

    Message::new

    fn Message::new(msg_type : MessageType, code : Code, mid : Int) -> Message

    Message::not_equal

    fn Message::not_equal(x : Message, y : Message) -> Bool

    Message::option_values

    fn Message::option_values(self : Message, number : Int) -> Array[Bytes]

    Message::remove_option

    fn Message::remove_option(self : Message, number : Int) -> Unit

    Message::replace_option

    fn Message::replace_option(self : Message, number : Int, value : Bytes) -> Unit

    Message::to_repr

    MessageType

    pub(all) enum MessageType {
    Confirmable
    NonConfirmable
    Acknowledgement
    Reset
    } derive(Eq,
    Debug
    )

    MessageType::equal

    fn MessageType::equal(MessageType, MessageType) -> Bool

    MessageType::not_equal

    fn MessageType::not_equal(x : MessageType, y : MessageType) -> Bool

    MessageType::wire

    fn MessageType::wire(self : MessageType) -> Int

    Method

    pub(all) enum Method {
    Get
    Post
    Put
    Delete
    } derive(Eq,
    Debug
    )

    Method::equal

    fn Method::equal(Method, Method) -> Bool

    Method::name

    fn Method::name(self : Method) -> String

    Method::not_equal

    fn Method::not_equal(x : Method, y : Method) -> Bool

    Method::to_repr

    Method::wire

    fn Method::wire(self : Method) -> Int

    OptionKind

    pub(all) enum OptionKind {
    Opaque
    Unsigned
    Text
    Flag
    } derive(Eq,
    Debug
    )

    OptionKind::equal

    fn OptionKind::equal(OptionKind, OptionKind) -> Bool

    OptionKind::not_equal

    fn OptionKind::not_equal(x : OptionKind, y : OptionKind) -> Bool

    OptionSpec

    pub(all) struct OptionSpec {
    number : Int
    name : String
    kind : OptionKind
    min_length : Int
    max_length : Int
    repeatable : Bool
    request_only : Bool
    response_only : Bool
    } derive(Eq,
    Debug
    )

    OptionSpec::equal

    fn OptionSpec::equal(OptionSpec, OptionSpec) -> Bool

    OptionSpec::not_equal

    fn OptionSpec::not_equal(x : OptionSpec, y : OptionSpec) -> Bool

    Representation

    pub(all) struct Representation {
    payload : Bytes
    content_format : Int
    etag : Bytes
    max_age : Int64
    } derive(Eq,
    Debug
    )

    Representation::equal

    Representation::not_equal

    fn Representation::not_equal(x : Representation, y : Representation) -> Bool

    Representation::response

    fn Representation::response(self : Representation, valid : Bool) -> Response

    Representation::validate

    fn Representation::validate(self : Representation, limits : Limits) -> Result[Unit, Failure]

    Request

    pub(all) struct Request {
    verb : Method
    options : Array[CoapOption]
    payload : Bytes
    confirmable : Bool
    } derive(Eq,
    Debug
    )

    Request::equal

    fn Request::equal(Request, Request) -> Bool

    Request::from_uri

    fn Request::from_uri(verb : Method, text : String, limits : Limits) -> Result[(CoapUri, Request), Failure]

    Request::new

    fn Request::new(verb : Method) -> Request

    Request::not_equal

    fn Request::not_equal(x : Request, y : Request) -> Bool

    Request::to_repr

    ResourceInfo

    pub(all) struct ResourceInfo {
    path : String
    content_format : Int
    size : Int
    etag : Bytes
    writable : Bool
    } derive(Eq,
    Debug
    )

    ResourceInfo::equal

    ResourceInfo::not_equal

    fn ResourceInfo::not_equal(x : ResourceInfo, y : ResourceInfo) -> Bool

    ResourceStore

    pub struct ResourceStore {
    // private fields
    }

    ResourceStore::byte_size

    fn ResourceStore::byte_size(self : ResourceStore) -> Int

    ResourceStore::discovery

    fn ResourceStore::discovery(self : ResourceStore, limits : Limits) -> Result[Discovery, Failure]

    ResourceStore::get

    fn ResourceStore::get(self : ResourceStore, path : String) -> Result[Representation, Failure]

    ResourceStore::handle

    fn ResourceStore::handle(self : ResourceStore, message : Message) -> Response

    ResourceStore::inventory

    fn ResourceStore::inventory(self : ResourceStore) -> Array[ResourceInfo]

    ResourceStore::new

    fn ResourceStore::new(capacity : Int, max_bytes : Int, formats : Array[Int], allow_create : Bool, limits : Limits) -> Result[ResourceStore, Failure]

    ResourceStore::put

    fn ResourceStore::put(self : ResourceStore, path : String, payload : Bytes, format : Int, max_age : Int64, writable : Bool) -> Result[Representation, Failure]

    ResourceStore::remove

    fn ResourceStore::remove(self : ResourceStore, path : String) -> Result[Bool, Failure]

    Response

    pub(all) struct Response {
    code : Code
    options : Array[CoapOption]
    payload : Bytes
    } derive(Eq,
    Debug
    )

    Response::content

    fn Response::content(payload : Bytes) -> Response

    Response::equal

    fn Response::equal(Response, Response) -> Bool

    Response::error

    fn Response::error(code : Int) -> Response

    Response::not_equal

    fn Response::not_equal(x : Response, y : Response) -> Bool

    Response::to_repr

    ResponseCache

    pub struct ResponseCache {
    // private fields
    }

    ResponseCache::clear

    fn ResponseCache::clear(self : ResponseCache) -> Int

    ResponseCache::invalidate

    fn ResponseCache::invalidate(self : ResponseCache, peer : String, path : String) -> Result[Int, Failure]

    ResponseCache::lookup

    fn ResponseCache::lookup(self : ResponseCache, peer : String, request : Request, now : Int64) -> Result[CacheLookup, Failure]

    ResponseCache::new

    fn ResponseCache::new(capacity : Int, max_bytes : Int, limits : Limits) -> Result[ResponseCache, Failure]

    ResponseCache::stats

    ResponseCache::store

    fn ResponseCache::store(self : ResponseCache, peer : String, request : Request, response : Response, now : Int64) -> Result[Unit, Failure]

    ResponseCache::validate

    fn ResponseCache::validate(self : ResponseCache, peer : String, request : Request, response : Response, now : Int64) -> Result[Unit, Failure]

    RouteMatch

    pub(all) struct RouteMatch {
    path : Array[Bytes]
    verb : Method
    } derive(Eq,
    Debug
    )

    RouteMatch::equal

    fn RouteMatch::equal(RouteMatch, RouteMatch) -> Bool

    RouteMatch::not_equal

    fn RouteMatch::not_equal(x : RouteMatch, y : RouteMatch) -> Bool

    Router

    pub struct Router {
    // private fields
    }

    Router::add

    fn Router::add(self : Router, path : String, verbs : Array[Method], handler : (IncomingRequest) -> Response) -> Result[Unit, Failure]

    Router::dispatch

    fn Router::dispatch(self : Router, incoming : IncomingRequest) -> Response

    Router::new

    fn Router::new(capacity : Int, limits : Limits) -> Result[Router, Failure]

    Router::remove

    fn Router::remove(self : Router, path : String) -> Result[Int, Failure]

    Router::routes

    fn Router::routes(self : Router) -> Array[RouteMatch]

    ServerView

    pub(all) struct ServerView {
    id : Int
    peer : String
    request_mid : Int
    token : Bytes
    expires_at : Int64
    acknowledged : Bool
    answered : Bool
    response_mid : Int?
    response_phase : ExchangePhase?
    response_deadline : Int64?
    last_sent_at : Int64?
    retransmissions : Int
    } derive(Eq,
    Debug
    )

    ServerView::equal

    fn ServerView::equal(ServerView, ServerView) -> Bool

    ServerView::not_equal

    fn ServerView::not_equal(x : ServerView, y : ServerView) -> Bool

    bytes_to_hex

    fn bytes_to_hex(bytes : Bytes) -> String

    cache_key

    fn cache_key(peer : String, request : Request, limits : Limits) -> Result[CacheKey, Failure]

    canonical_ipv6

    fn canonical_ipv6(text : String) -> Result[String, Failure]

    canonical_path

    fn canonical_path(parts : Array[Bytes]) -> String

    deadline_after

    fn deadline_after(now : Int64, delay : Int64) -> Result[Int64, Failure]

    decode

    fn decode(bytes : Bytes, limits : Limits) -> Result[Message, Failure]

    decode_utf8

    fn decode_utf8(bytes : Bytes) -> Result[String, Failure]

    empty_control

    fn empty_control(msg_type : MessageType, mid : Int) -> Message

    encode

    fn encode(message : Message, limits : Limits) -> Result[Bytes, Failure]

    encoded_size

    fn encoded_size(message : Message, limits : Limits) -> Result[Int, Failure]

    hex_to_bytes

    fn hex_to_bytes(text : String) -> Result[Bytes, Failure]

    message_uint

    fn message_uint(message : Message, number : Int, default_value : Int64) -> Result[Int64, Failure]

    option_is_cache_key

    fn option_is_cache_key(number : Int) -> Bool

    option_is_critical

    fn option_is_critical(number : Int) -> Bool

    option_is_unsafe

    fn option_is_unsafe(number : Int) -> Bool

    option_text

    fn option_text(number : Int, text : String) -> CoapOption

    option_to_text

    fn option_to_text(option : CoapOption) -> Result[String, Failure]

    option_to_uint

    fn option_to_uint(option : CoapOption) -> Result[Int64, Failure]

    option_uint

    fn option_uint(number : Int, value : Int64) -> Result[CoapOption, Failure]

    parse_ipv4

    fn parse_ipv4(text : String) -> Result[Array[Int], Failure]

    parse_ipv6

    fn parse_ipv6(text : String) -> Result[Array[Int], Failure]

    fn parse_links(payload : Bytes, limits : Limits) -> Result[Array[CoreLink], Failure]

    path_segments

    fn path_segments(message : Message) -> Array[Bytes]

    percent_decode

    fn percent_decode(text : String) -> Result[Bytes, Failure]

    percent_encode

    fn percent_encode(bytes : Bytes) -> String

    preconditions

    fn preconditions(message : Message, current : Representation?) -> Bool

    received_options

    fn received_options(message : Message, supported : Array[Int]) -> Result[Array[CoapOption], Failure]

    request_path

    fn request_path(message : Message) -> Result[String, Failure]

    request_queries

    fn request_queries(message : Message) -> Result[Array[String], Failure]

    resource_path

    fn resource_path(path : String, limits : Limits) -> Result[Array[Bytes], Failure]

    retry_interval

    fn retry_interval(config : Config, random_sample : Int) -> Result[Int64, Failure]

    select_representation

    fn select_representation(message : Message, current : Representation) -> Response

    fn serialize_links(links : Array[CoreLink], limits : Limits) -> Result[Bytes, Failure]

    standard_option

    fn standard_option(number : Int) -> OptionSpec?

    validate_options

    fn validate_options(message : Message, supported_critical : Array[Int]) -> Result[Unit, Failure]