--- title: ternary tags: RFC, published --- + Feature name: (fill me in with a unique ident, `my_awesome_feature`) + Start date: (fill me in with today's date, YYYY-MM-DD) + RFC PR: [iotaledger/bee-rfcs#0000](https://github.com/iotaledger/bee-rfcs/pull/0000) + Bee issue: [iotaledger/bee#0000](https://github.com/iotaledger/bee/issues/0000) # Summary In this RFC we introduce both the API and implementation of the `bee-ternary` crate, a general-purpose ternary manipulation crate written in Rust that may be used throughout the IOTA ecosystem. # Motivation Ternary is a fundamental part of the IOTA ecosystem and is used throughout, even for fundamental features like wallet addresses and transaction identification. Manipulating ternary in an ergonomic manner on top of existing binary-driven code can require complexity and, up until now, comes either with a lot of boilerplate code, implementations that are difficult to verify as correct, or a lack of features. `bee-ternary` seeks to become the canonical ternary crate in the Rust IOTA ecosystem by providing an API that is efficient, ergonomic, and featureful all at once. We hope that `bee-ternary` will allow IOTA developers to more easily write code that works with ternary and allow the simplification of existing codebases through use of the API. Broadly, there are 3 main benefits things that `bee-ternary` aims to provide over use-specific implementations of ternary manipulation code. - **Ergonomics**: The API should be trivial to use correctly and should naturally guide developers towards correct and efficient solutions. - **Features**: The API should provide a powerful set of core features that can be used together to cover most developer requirements. Examples of such features include multiple encoding schemes, binary/ternary conversion, (de)serialization, and tryte string de/encoding. - **Performance**: The API should allow 'acceptably' efficient manipulation of ternary data. This is difficult to ruggedly define, and implementation details may change later, but broadly we intend to introduce an API that doesn't inherently inhibit high performance through poor design choices. # Detailed design `bee-ternary` is designed to be extensible and is built on top of a handful of powerful abstraction types. Below we list the features of the API and summarise a few of the core API objects. ## Features - Efficient manipulation of ternary buffers (trits and trytes) - Multiple encoding schemes - Extensible design that allows it to sit on top of existing data structures, avoiding unnecessary allocation and copying - A plethora of utility functions to allow for easy manipulation of ternary data - Zero-cost conversion between trit and tryte formats ## Key Types & Traits ### `Trits` ```rust struct Trits<T: RawEncoding> { ... } ``` - Analogous to `str` or `[T]` - Unsized type, represents a buffer of trits of a specified encoding - Most commonly used from behind a reference (as with `&str` and `&[T]`), representing a 'trit slice' - Can be created from a variety of types such as`TritBuf` and `[i8]` with minimal overhead - Sub-slices can be created from trit slices at a per-trit level ### `TritBuf` ``` struct TritBuf<T: RawEncodingBuf> { ... } ``` - Analogous to `String` or `Vec<T>` - Most common way to manipulate trits - Allows pushing, popping, and collecting trits - Implements `Deref<Target=Trits>` (in the same way that `Vec<T>` implements `Deref<[T]>`) ### `RawEncoding` ``` trait RawEncoding { ... } ``` - Represents a raw trit buffer of some encoding - Common interface implemented by all trit encodings (`T1B1`, `T3B1`, `T5B1`, etc.) - Largely an implementation detail, not something you need to care about unless implementing your own encodings - Minimal implementation requirements: safety and most utility functionality is provided by `Trits` instead ### `RawEncodingBuf` ``` trait RawEncodingBuf { ... } ``` - Buffer counterpart of `RawEncoding`, always associated with a specific `RawEncoding` - Distinct from `RawEncoding` to permit different buffer-like data structures in the future (linked lists, stack-allocated arrays, etc.) ## Common Patterns When using the API, the most common types interacted with are `Trits` and `TritBuf`. # Drawbacks Why should we *not* do this? # Rationale and alternatives - Why is this design the best in the space of possible designs? - What other designs have been considered and what is the rationale for not choosing them? - What is the impact of not doing this? # Unresolved questions - What parts of the design do you expect to resolve through the RFC process before this gets merged? - What parts of the design do you expect to resolve through the implementation of this feature before stabilization? - What related issues do you consider out of scope for this RFC that could be addressed in the future independently of the solution that comes out of this RFC?