net: add epee-encoding and fixed-bytes

This commit is contained in:
Boog900 2024-01-29 22:32:16 +00:00
parent 1b8bfb8a32
commit 2b65be4b18
No known key found for this signature in database
GPG key ID: 5401367FB7302004
25 changed files with 2973 additions and 91 deletions

38
Cargo.lock generated
View file

@ -596,6 +596,18 @@ version = "1.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07"
[[package]]
name = "epee-encoding"
version = "0.5.0"
dependencies = [
"bytes",
"fixed-bytes",
"hex",
"paste",
"sealed",
"thiserror",
]
[[package]]
name = "equivalent"
version = "1.0.1"
@ -656,6 +668,14 @@ version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "27573eac26f4dd11e2b1916c3fe1baa56407c83c71a773a8ba17ec0bca03b6b7"
[[package]]
name = "fixed-bytes"
version = "0.1.0"
dependencies = [
"bytes",
"thiserror",
]
[[package]]
name = "flexible-transcript"
version = "0.3.2"
@ -1313,6 +1333,12 @@ dependencies = [
"subtle",
]
[[package]]
name = "paste"
version = "1.0.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c"
[[package]]
name = "pbkdf2"
version = "0.12.2"
@ -1694,6 +1720,18 @@ dependencies = [
"untrusted",
]
[[package]]
name = "sealed"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f4a8caec23b7800fb97971a1c6ae365b6239aaeddfb934d6265f8505e795699d"
dependencies = [
"heck",
"proc-macro2",
"quote",
"syn 2.0.48",
]
[[package]]
name = "security-framework"
version = "2.9.2"

View file

@ -6,6 +6,8 @@ members = [
"consensus/rules",
"cryptonight",
"helper",
"net/epee-encoding",
"net/fixed-bytes",
"net/levin",
"net/monero-wire",
"p2p/monero-p2p",

View file

@ -42,13 +42,16 @@ meaning other parts of the node will have no P2P code except from sending reques
This endpoint will be made of a few different tower::Services for the different routing methods, the most
simple method is to use a load balancing algorithm to send a request to one peer.
The peer to peer part of Cuprate will be split into 3 crates:
The peer to peer part of Cuprate will be split into multiple crates:
| Name | Short Description |
|---------------|-----------------------------------------------------------------------------------------------|
|---------------------|----------------------------------------------------------------------------------------------------------------|
| levin-cuprate | A library containing the levin header format. |
| monero-wire | A library containing all Monero P2P messages built on-top of `levin-cuprate`. |
| cuprate-p2p | A library abstracting the P2P network away, with logic for handshakes, the address book, etc. |
| monero-p2p | A library defining the network zone abstraction and individual peer logic (handshakes etc). |
| monero-address-book | Contains the P2P address book, handles storing peers, getting peers etc. |
| cuprate-p2p | Defines the PeerSet and the different routing methods (excluding d++), has the logic for starting the network. |
| dandelion-pp | Defines the D++ routing method. |
#### levin-cuprate
@ -63,24 +66,29 @@ This will be a library built on top of [levin-cuprate](#levin-cuprate), It will
message with decoding/ encoding capability. This library will implement the `LevinMessage` trait.
The serialization format used for P2P messages has already been implemented in Rust, multiple times :). I have decided to
implement it yet again in the crate: `epee-encoding`. This crate was created specifically for use in Cuprate.
use monero-epee-bin-serde.
The monero-wire crate will be able to be used in other Rust projects who want to interact with Monero's P2P network.
The monero-wire crate can be used in other Rust projects which need Monero's p2p network messages.
#### cuprate-p2p
#### monero-p2p
This library will abstract the P2P network away into one endpoint. Sadly, this endpoint will have to be made
up of different tower::Services for the different routing methods. For example, new blocks need to be sent to every
peer but a request may only need to go to a single peer.
This library will contain the network zone abstraction, which abstracts over clear-net, Tor, I2P and any future network.
The library will be split into many modules:
This will also contain a `Client` and `Connection`. The `Connection` will be an async task that gives requests from
the peer to the inbound request handler and sends requests from Cuprate to the peer. The `Client` will implement
tower::Service and will simply pass requests from our node to the `Connection` task.
##### protocol
This will also contain a `Handshaker` which is responsible for taking a peer connection doing a handshake with it
and creating a `Client` and `Connection`.
This library is intended to be a more flexible monero p2p library than what cuprate-p2p is, allowing wider use in applications that need to
interact with Monero's p2p network but don't want/ or need Cuprates whole p2p stack.
To be compatible with tower::Service the Monero P2P protocol needs to be split into requests and responses.
Levin admin messages are already in the request/ response format, but notifications are not. For some
notifications it's easy: `GetObjectsRequest` but for others it's harder.
Here is a table of the Monero P2P messages put in either requests or responses:
```
/// Admin (These are already in request/ response format):
/// Handshake,
@ -100,41 +108,32 @@ Here is a table of the Monero P2P messages put in either requests or responses:
To split messages that can be requests or responses we will need to keep track of sent
requests.
##### peer
#### monero-address-book
This will contain a `Client` and `Connection`. The `Connection` will be an async task that gives requests from
the peer to the inbound request handler and sends requests from Cuprate to the peer. The `Client` will implement
tower::Service and will simply pass requests from our node to the `Connection` task.
This implements Monero's p2p address book, this is a separate crate to monero-p2p to allow developers to create their own address book implementation
if `monero-address-book` is not suitable for them. `monero-address-book` will implement an `AddressBook` trait defined in `monero-p2p`.
This module will also contain a `Handshaker` which is responsible for taking a peer connection doing a handshake with it
and creating a `Client` and `Connection`.
#### cuprate-p2p
##### address book
This library will abstract the P2P network away into one endpoint. Sadly, this endpoint will have to be made
up of different tower::Services for the different routing methods. For example, new blocks need to be sent to every
peer but a request for a block may only need to go to a single peer.
The address book will use the same overall idea as monerod's address book. It will contain a White, Grey and Anchor
list. Under the hood we will have 3 separate address books for each network (clear, i2p, Tor) and will route requests
using a tower::Steer.
To allow splitting the endpoint into multiple tower::Services a `PeerSet` will be defined that will be shared between the services and is the structure
that holds on the currently connected peer on a certain network. The tower::Services will use this `PeerSet` to get peers to route requests to.
White: Peers we have connected to at some point.
`cuprate-p2p` will also have a block downloader which will be a `futures::Stream`, it will use the `PeerSet` to find the chain with the highest cumulative
difficulty and download that chain, when it gets a block it will pass it back through the `Stream`.
Gray: Peers we have heard about but haven't attempted to connect to.
#### dandelion-pp
Anchor: A list of currently connected peers so, if we were to re-start, we can choose a couple peers from this list to
reduce our chance of being isolated.
This crate is separate from the other routing methods to allow wider usage, to do this it will be generic over the requests/ responses allowing users
to define them.
The address book will be an async task which we will be able to interact with through a tower::Service.
This crate won't be able to handle all of dandelion++ as that requires knowledge of the tx-pool but it will handle all of the routing side, deciding the current
state, getting the peers to route to etc.
##### peer set
This is the part of the P2P crate that holds all currently connected peers. The rest of Cuprate will interact with this
structure to send requests to the network. There will be multiple tower::Service interfaces to interact with the network
for the different routing methods:
- broadcast: send a message to all ready `Clients`
- single: use a load balancing algorithm to route a message to a single `Client`
- multiple: sends a request to an amount of peers chosen by the requester, this might be joined with broadcast.
*There may be more routing methods in the future*
Each request will have to include an origin, e.g self, fluff, so the d++ can route it correctly.
---
@ -164,34 +163,6 @@ monero-serai already has the API to allow batch verification of bulletproofs(+).
transactions will also allow us to use a thread-pool like `rayon` to parallelize verification that can't
be batched.
Transaction verification will be split into 2 sections: hard and soft.
##### Hard:
If a transaction fails this, the node will reject the transaction completely including in blocks.
##### Soft:
If a transaction fails this, the node won't broadcast the transaction but will allow it in blocks.
This is to make it easy to do things like stopping transaction with too large extra fields and making transactions
follow a standard decoy selection algorithm (this isn't planned) without the need for a hard fork.
---
### Syncer
The syncer will be responsible for syncing the blockchain after falling behind. It will utilize many of the components
we have discussed, a new tower::Service is needed though `The block downloader`.
#### The block downloader
This will be responsible for finding the chain tip and getting blocks from peers, it does no verification* and simply gets
the next block.
(*) some verification may be done here just to see if the block we got is the one we asked for but TBD.
The syncer will call the block downloader to get the chain-tip then it will call for the next batch of blocks, when it has this batch
it will send it to the block verifier, which will return if the blocks are valid, if they are we add them to our blockchain.
---
### Database

View file

@ -0,0 +1,26 @@
[package]
name = "epee-encoding"
version = "0.5.0"
edition = "2021"
license = "MIT"
authors = ["Boog900"]
readme = "README.md"
keywords = ["monero", "epee", "no-std"]
description = "Epee binary format library."
repository = "https://github.com/Boog900/epee-encoding"
rust-version = "1.60"
[features]
default = ["std"]
std = ["dep:thiserror", "bytes/std", "fixed-bytes/std"]
[dependencies]
fixed-bytes = { path = "../fixed-bytes", default-features = false }
sealed = "0.5.0"
paste = "1.0.14"
bytes = { workspace = true }
thiserror = { workspace = true, optional = true}
[dev-dependencies]
hex = { workspace = true, features = ["default"] }

21
net/epee-encoding/LICENSE Normal file
View file

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2023 Boog900
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

202
net/epee-encoding/README.md Normal file
View file

@ -0,0 +1,202 @@
# Epee Encoding
- [What](#what)
- [Features](#features)
- [Usage](#usage)
- [Derive Attributes](#derive-attributes)
- [No std](#no-std)
- [Options](#options)
## What
This crate implements the epee binary format found in Monero; unlike other crates,
this one does not use serde, this is not because serde is bad but its to reduce the
load on maintainers as all the traits in this lib are specific to epee instead of
general purpose.
## Features
### Default
The default feature enables the [derive](#derive) feature.
### Derive
This feature enables the derive macro for creating epee objects for example:
```rust
use epee_encoding::EpeeObject;
#[derive(EpeeObject)]
struct Test {
val: u8
}
```
## Usage
### example without derive:
```rust
use epee_encoding::{EpeeObject, EpeeObjectBuilder, read_epee_value, write_field, to_bytes, from_bytes};
use epee_encoding::io::{Read, Write};
pub struct Test {
val: u64
}
#[derive(Default)]
pub struct __TestEpeeBuilder {
val: Option<u64>,
}
impl EpeeObjectBuilder<Test> for __TestEpeeBuilder {
fn add_field<R: Read>(&mut self, name: &str, r: &mut R) -> epee_encoding::error::Result<bool> {
match name {
"val" => {self.val = Some(read_epee_value(r)?);}
_ => return Ok(false),
}
Ok(true)
}
fn finish(self) -> epee_encoding::error::Result<Test> {
Ok(
Test {
val: self.val.ok_or_else(|| epee_encoding::error::Error::Format("Required field was not found!"))?
}
)
}
}
impl EpeeObject for Test {
type Builder = __TestEpeeBuilder;
fn number_of_fields(&self) -> u64 {
1
}
fn write_fields<W: Write>(&self, w: &mut W) -> epee_encoding::error::Result<()> {
// write the fields
write_field(&self.val, "val", w)
}
}
let data = [1, 17, 1, 1, 1, 1, 2, 1, 1, 4, 3, 118, 97, 108, 5, 4, 0, 0, 0, 0, 0, 0, 0]; // the data to decode;
let val: Test = from_bytes(&data).unwrap();
let data = to_bytes(&val).unwrap();
```
### example with derive:
```rust
use epee_encoding::{EpeeObject, from_bytes, to_bytes};
#[derive(EpeeObject)]
struct Test {
val: u64
}
let data = [1, 17, 1, 1, 1, 1, 2, 1, 1, 4, 3, 118, 97, 108, 5, 4, 0, 0, 0, 0, 0, 0, 0]; // the data to decode;
let val: Test = from_bytes(&data).unwrap();
let data = to_bytes(&val).unwrap();
```
## Derive Attributes
The `EpeeObject` derive macro has a few attributes which correspond to specific C/C++ macro fields.
- [epee_flatten](#epeeflatten)
- [epee_alt_name](#epeealtname)
- [epee_default](#epeedefault)
### epee_flatten
This is equivalent to `KV_SERIALIZE_PARENT`, it flattens all the fields in the object into the parent object.
so this in C/C++:
```cpp
struct request_t: public rpc_request_base
{
uint8_t major_version;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE_PARENT(rpc_request_base)
KV_SERIALIZE(major_version)
END_KV_SERIALIZE_MAP()
};
```
Would look like this in Rust:
```rust
#[derive(EpeeObject)]
struct RequestT {
#[epee_flatten]
rpc_request_base: RequestBase,
major_version: u8,
}
```
### epee_alt_name
This allows you to re-name a field for when its encoded, although this isn't related to a specific macro in
C/C++ this was included because Monero has [some odd names](https://github.com/monero-project/monero/blob/0a1eaf26f9dd6b762c2582ee12603b2a4671c735/src/cryptonote_protocol/cryptonote_protocol_defs.h#L199).
example:
```rust
#[derive(EpeeObject)]
pub struct HandshakeR {
#[epee_alt_name("node_data")]
pub node_daa: BasicNodeData,
}
```
### epee_default
This is equivalent to `KV_SERIALIZE_OPT` and allows you to specify a default value for a field, when a default value
is specified the value will be used if it is not contained in the data and the field will not be encoded if the value is
the default value.
so this in C/C++:
```cpp
struct request_t
{
std::vector<blobdata> txs;
std::string _; // padding
bool dandelionpp_fluff; //zero initialization defaults to stem mode
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(txs)
KV_SERIALIZE(_)
KV_SERIALIZE_OPT(dandelionpp_fluff, true) // backwards compatible mode is fluff
END_KV_SERIALIZE_MAP()
};
```
would look like this in Rust:
```rust
#[derive(EpeeObject)]
struct RequestT {
txs: Vec<Vec<u8>>,
#[epee_alt_name("_")]
padding: Vec<u8>,
#[epee_default(true)]
dandelionpp_fluff: bool,
}
```
## No std
This crate is no-std.
## Options
To have an optional field, you should wrap the type in `Option` and use the `epee_default` attribute.
So it would look like this:
```rust
#[derive(EpeeObject)]
struct T {
#[epee_default(None)]
val: Option<u8>,
}
```

View file

@ -0,0 +1,52 @@
use core::fmt::{Debug, Formatter};
use core::{num::TryFromIntError, str::Utf8Error};
pub type Result<T> = core::result::Result<T, Error>;
#[cfg_attr(feature = "std", derive(thiserror::Error))]
pub enum Error {
#[cfg_attr(feature = "std", error("IO error: {0}"))]
IO(&'static str),
#[cfg_attr(feature = "std", error("Format error: {0}"))]
Format(&'static str),
#[cfg_attr(feature = "std", error("Value error: {0}"))]
Value(&'static str),
}
impl Error {
fn field_name(&self) -> &'static str {
match self {
Error::IO(_) => "io",
Error::Format(_) => "format",
Error::Value(_) => "value",
}
}
fn field_data(&self) -> &'static str {
match self {
Error::IO(data) => data,
Error::Format(data) => data,
Error::Value(data) => data,
}
}
}
impl Debug for Error {
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
f.debug_struct("Error")
.field(self.field_name(), &self.field_data())
.finish()
}
}
impl From<TryFromIntError> for Error {
fn from(_: TryFromIntError) -> Self {
Error::Value("Int is too large")
}
}
impl From<Utf8Error> for Error {
fn from(_: Utf8Error) -> Self {
Error::Value("Invalid utf8 str")
}
}

View file

@ -0,0 +1,44 @@
use bytes::{Buf, BufMut};
use crate::error::*;
#[inline]
pub fn checked_read_primitive<B: Buf, R: Sized>(
b: &mut B,
read: impl Fn(&mut B) -> R,
) -> Result<R> {
checked_read(b, read, core::mem::size_of::<R>())
}
#[inline]
pub fn checked_read<B: Buf, R>(b: &mut B, read: impl Fn(&mut B) -> R, size: usize) -> Result<R> {
if b.remaining() < size {
Err(Error::IO("Not enough bytes in buffer to build object."))?;
}
Ok(read(b))
}
#[inline]
pub fn checked_write_primitive<B: BufMut, T: Sized>(
b: &mut B,
write: impl Fn(&mut B, T),
t: T,
) -> Result<()> {
checked_write(b, write, t, core::mem::size_of::<T>())
}
#[inline]
pub fn checked_write<B: BufMut, T>(
b: &mut B,
write: impl Fn(&mut B, T),
t: T,
size: usize,
) -> Result<()> {
if b.remaining_mut() < size {
Err(Error::IO("Not enough capacity to write object."))?;
}
write(b, t);
Ok(())
}

View file

@ -0,0 +1,317 @@
#![cfg_attr(not(feature = "std"), no_std)]
//! Epee Encoding
//!
//! This library contains the Epee binary format found in Monero, unlike other
//! crates this crate does not use serde.
//!
//! example without macro:
//! ```rust
//! # use epee_encoding::{EpeeObject, EpeeObjectBuilder, read_epee_value, write_field, to_bytes, from_bytes};
//! # use bytes::{Buf, BufMut};
//!
//! pub struct Test {
//! val: u64
//! }
//!
//! #[derive(Default)]
//! pub struct __TestEpeeBuilder {
//! val: Option<u64>,
//! }
//!
//! impl EpeeObjectBuilder<Test> for __TestEpeeBuilder {
//! fn add_field<B: Buf>(&mut self, name: &str, r: &mut B) -> epee_encoding::error::Result<bool> {
//! match name {
//! "val" => {self.val = Some(read_epee_value(r)?);}
//! _ => return Ok(false),
//! }
//! Ok(true)
//! }
//!
//! fn finish(self) -> epee_encoding::error::Result<Test> {
//! Ok(
//! Test {
//! val: self.val.ok_or_else(|| epee_encoding::error::Error::Format("Required field was not found!"))?
//! }
//! )
//! }
//! }
//!
//! impl EpeeObject for Test {
//! type Builder = __TestEpeeBuilder;
//!
//! fn number_of_fields(&self) -> u64 {
//! 1
//! }
//!
//! fn write_fields<B: BufMut>(self, w: &mut B) -> epee_encoding::error::Result<()> {
//! // write the fields
//! write_field(self.val, "val", w)
//! }
//! }
//!
//!
//! let data = [1, 17, 1, 1, 1, 1, 2, 1, 1, 4, 3, 118, 97, 108, 5, 4, 0, 0, 0, 0, 0, 0, 0]; // the data to decode;
//! let val: Test = from_bytes(&data).unwrap();
//! let data = to_bytes(val).unwrap();
//!
//!
//! ```
//!
//! example with macro:
//! ```rust
//! use epee_encoding::{from_bytes, to_bytes};
//!
//! // TODO: open an issue documenting why you need to do this here
//! // like this: https://github.com/Boog900/epee-encoding/issues/1
//! mod i_64079 {
//! use epee_encoding::epee_object;
//!
//! pub struct Test2 {
//! val: u64
//! }
//!
//! epee_object!(
//! Test2,
//! val: u64,
//! );
//! }
//! use i_64079::*;
//!
//!
//! let data = [1, 17, 1, 1, 1, 1, 2, 1, 1, 4, 3, 118, 97, 108, 5, 4, 0, 0, 0, 0, 0, 0, 0]; // the data to decode;
//! let val: Test2 = from_bytes(&data).unwrap();
//! let data = to_bytes(val).unwrap();
//!
//! ```
extern crate alloc;
use alloc::vec::Vec;
use core::{ops::Deref, str::from_utf8 as str_from_utf8};
use bytes::{Buf, BufMut, Bytes};
pub mod error;
mod io;
pub mod macros;
pub mod marker;
mod value;
mod varint;
pub use error::*;
use io::*;
pub use marker::{InnerMarker, Marker};
pub use value::EpeeValue;
use varint::*;
/// Header that needs to be at the beginning of every binary blob that follows
/// this binary serialization format.
const HEADER: &[u8] = b"\x01\x11\x01\x01\x01\x01\x02\x01\x01";
/// The maximum length a byte array (marked as a string) can be.
const MAX_STRING_LEN_POSSIBLE: u64 = 2000000000;
/// The maximum depth of skipped objects.
const MAX_DEPTH_OF_SKIPPED_OBJECTS: u8 = 20;
/// The maximum number of fields in an object.
const MAX_NUM_FIELDS: u64 = 1000;
/// A trait for an object that can build a type `T` from the epee format.
pub trait EpeeObjectBuilder<T>: Default + Sized {
/// Called when a field names has been read no other bytes following the field
/// name will have been read.
///
/// Returns a bool if true then the field has been read otherwise the field is not
/// needed and has not been read.
fn add_field<B: Buf>(&mut self, name: &str, b: &mut B) -> Result<bool>;
/// Called when the number of fields has been read.
fn finish(self) -> Result<T>;
}
/// A trait for an object that can be turned into epee bytes.
pub trait EpeeObject: Sized {
type Builder: EpeeObjectBuilder<Self>;
/// Returns the number of fields to be encoded.
fn number_of_fields(&self) -> u64;
/// write the objects fields into the writer.
fn write_fields<B: BufMut>(self, w: &mut B) -> Result<()>;
}
/// Read the object `T` from a byte array.
pub fn from_bytes<T: EpeeObject>(mut buf: &[u8]) -> Result<T> {
read_head_object(&mut buf)
}
/// Turn the object into epee bytes.
pub fn to_bytes<T: EpeeObject>(val: T) -> Result<Vec<u8>> {
let mut buf = Vec::<u8>::new();
write_head_object(val, &mut buf)?;
Ok(buf)
}
fn read_header<B: Buf>(r: &mut B) -> Result<()> {
let buf = checked_read(r, |b: &mut B| b.copy_to_bytes(HEADER.len()), HEADER.len())?;
if buf.deref() != HEADER {
return Err(Error::Format("Data does not contain header"));
}
Ok(())
}
fn write_header<B: BufMut>(w: &mut B) -> Result<()> {
checked_write(w, BufMut::put_slice, HEADER, HEADER.len())
}
fn write_head_object<T: EpeeObject, B: BufMut>(val: T, w: &mut B) -> Result<()> {
write_header(w)?;
val.write(w)
}
fn read_head_object<T: EpeeObject, B: Buf>(r: &mut B) -> Result<T> {
read_header(r)?;
let mut skipped_objects = 0;
read_object(r, &mut skipped_objects)
}
fn read_field_name_bytes<B: Buf>(r: &mut B) -> Result<Bytes> {
let len: usize = r.get_u8().into();
checked_read(r, |b: &mut B| b.copy_to_bytes(len), len)
}
fn write_field_name<B: BufMut>(val: &str, w: &mut B) -> Result<()> {
checked_write_primitive(w, BufMut::put_u8, val.len().try_into()?)?;
let slice = val.as_bytes();
checked_write(w, BufMut::put_slice, slice, slice.len())
}
/// Write an epee field.
pub fn write_field<T: EpeeValue, B: BufMut>(val: T, field_name: &str, w: &mut B) -> Result<()> {
if val.should_write() {
write_field_name(field_name, w)?;
write_epee_value(val, w)?;
}
Ok(())
}
fn read_object<T: EpeeObject, B: Buf>(r: &mut B, skipped_objects: &mut u8) -> Result<T> {
let mut object_builder = T::Builder::default();
let number_o_field = read_varint(r)?;
if number_o_field > MAX_NUM_FIELDS {
return Err(Error::Format(
"Data has object with more fields than the maximum allowed",
));
}
for _ in 0..number_o_field {
let field_name_bytes = read_field_name_bytes(r)?;
let field_name = str_from_utf8(field_name_bytes.deref())?;
if !object_builder.add_field(field_name, r)? {
skip_epee_value(r, skipped_objects)?;
}
}
object_builder.finish()
}
/// Read a marker from the [`Read`], this function should only be used for
/// custom serialisation based on the marker otherwise just use [`read_epee_value`].
pub fn read_marker<B: Buf>(r: &mut B) -> Result<Marker> {
Marker::try_from(checked_read_primitive(r, Buf::get_u8)?)
}
/// Read an epee value from the stream, an epee value is the part after the key
/// including the marker.
pub fn read_epee_value<T: EpeeValue, B: Buf>(r: &mut B) -> Result<T> {
let marker = read_marker(r)?;
T::read(r, &marker)
}
/// Write an epee value to the stream, an epee value is the part after the key
/// including the marker.
fn write_epee_value<T: EpeeValue, B: BufMut>(val: T, w: &mut B) -> Result<()> {
checked_write_primitive(w, BufMut::put_u8, T::MARKER.as_u8())?;
val.write(w)
}
/// A helper object builder that just skips every field.
#[derive(Default)]
struct SkipObjectBuilder;
impl EpeeObjectBuilder<SkipObject> for SkipObjectBuilder {
fn add_field<B: Buf>(&mut self, _name: &str, _r: &mut B) -> Result<bool> {
Ok(false)
}
fn finish(self) -> Result<SkipObject> {
Ok(SkipObject)
}
}
/// A helper object that just skips every field.
struct SkipObject;
impl EpeeObject for SkipObject {
type Builder = SkipObjectBuilder;
fn number_of_fields(&self) -> u64 {
panic!("This is a helper function to use when de-serialising")
}
fn write_fields<B: BufMut>(self, _w: &mut B) -> Result<()> {
panic!("This is a helper function to use when de-serialising")
}
}
/// Skip an epee value, should be used when you do not need the value
/// stored at a key.
fn skip_epee_value<B: Buf>(r: &mut B, skipped_objects: &mut u8) -> Result<()> {
let marker = read_marker(r)?;
let mut len = 1;
if marker.is_seq {
len = read_varint(r)?;
}
if let Some(size) = marker.inner_marker.size() {
let bytes_to_skip = size
.checked_mul(len.try_into()?)
.ok_or(Error::Value("List is too big"))?;
return advance(bytes_to_skip, r);
};
for _ in 0..len {
match marker.inner_marker {
InnerMarker::I64
| InnerMarker::U64
| InnerMarker::F64
| InnerMarker::I32
| InnerMarker::U32
| InnerMarker::I16
| InnerMarker::U16
| InnerMarker::I8
| InnerMarker::U8
| InnerMarker::Bool => unreachable!("These types are constant size."),
InnerMarker::String => {
let len = read_varint(r)?;
advance(len.try_into()?, r)?;
}
InnerMarker::Object => {
*skipped_objects += 1;
if *skipped_objects > MAX_DEPTH_OF_SKIPPED_OBJECTS {
return Err(Error::Format("Depth of skipped objects exceeded maximum"));
}
read_object::<SkipObject, _>(r, skipped_objects)?;
*skipped_objects -= 1;
}
};
}
Ok(())
}
fn advance<B: Buf>(n: usize, b: &mut B) -> Result<()> {
checked_read(b, |b: &mut B| b.advance(n), n)
}

View file

@ -0,0 +1,125 @@
pub use bytes;
pub use paste::paste;
#[macro_export]
macro_rules! field_name {
($field: ident, $alt_name: literal) => {
$alt_name
};
($field: ident,) => {
stringify!($field)
};
}
#[macro_export]
macro_rules! field_ty {
($ty:ty, $ty_as:ty) => {
$ty_as
};
($ty:ty,) => {
$ty
};
}
#[macro_export]
macro_rules! epee_object {
(
$obj:ident,
$($field: ident $(($alt_name: literal))?: $ty:ty $(= $default:literal)? $(as $ty_as:ty)?, )+
$(!flatten: $($flat_field: ident: $flat_ty:ty ,)+)?
) => {
epee_encoding::macros::paste!(
#[allow(non_snake_case)]
mod [<__epee_builder_ $obj>] {
use super::*;
#[derive(Default)]
pub struct [<__Builder $obj>] {
$($field: Option<epee_encoding::field_ty!($ty, $($ty_as)?)>,)+
$($($flat_field: <$flat_ty as epee_encoding::EpeeObject>::Builder,)+)?
}
impl epee_encoding::EpeeObjectBuilder<$obj> for [<__Builder $obj>] {
fn add_field<B: epee_encoding::macros::bytes::Buf>(&mut self, name: &str, b: &mut B) -> epee_encoding::error::Result<bool> {
match name {
$(epee_encoding::field_name!($field, $($alt_name)?) => {
if core::mem::replace(&mut self.$field, Some(epee_encoding::read_epee_value(b)?)).is_some() {
Err(epee_encoding::error::Error::Value("Duplicate field in data"))?;
}
Ok(true)
},)+
_ => {
$(
$( if self.$flat_field.add_field(name, b)? {
return Ok(true);
})+
)?
Ok(false)
}
}
}
fn finish(self) -> epee_encoding::error::Result<$obj> {
Ok(
$obj {
$(
$field: self.$field
$(.or(Some($default)))?
.or(epee_encoding::EpeeValue::epee_default_value())
$(.map(<$ty_as>::into))?
.ok_or(epee_encoding::error::Error::Value("Missing field in data"))?,
)+
$(
$(
$flat_field: self.$flat_field.finish()?,
)+
)?
}
)
}
}
}
impl epee_encoding::EpeeObject for $obj {
type Builder = [<__epee_builder_ $obj>]::[<__Builder $obj>];
fn number_of_fields(&self) -> u64 {
let mut fields = 0;
$(
if $(&self.$field != &$default &&)? epee_encoding::EpeeValue::should_write($(<&$ty_as>::from)?( &self.$field) ) {
fields += 1;
}
)+
$(
$(
fields += self.$flat_field.number_of_fields();
)+
)?
fields
}
fn write_fields<B: epee_encoding::macros::bytes::BufMut>(self, w: &mut B) -> epee_encoding::error::Result<()> {
$(
if $(&self.$field != &$default &&)? epee_encoding::EpeeValue::should_write($(<&$ty_as>::from)?( &self.$field) ) {
epee_encoding::write_field($(<$ty_as>::from)?(self.$field), epee_encoding::field_name!($field, $($alt_name)?), w)?;
}
)+
$(
$(
self.$flat_field.write_fields(w)?;
)+
)?
Ok(())
}
}
);
};
}

View file

@ -0,0 +1,120 @@
/// This module contains a [`Marker`] which is appended before each value to tell you the type.
use crate::Error;
/// The inner marker just telling you the type.
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
pub enum InnerMarker {
I64,
I32,
I16,
I8,
U64,
U32,
U16,
U8,
F64,
String,
Bool,
Object,
}
impl InnerMarker {
pub fn size(&self) -> Option<usize> {
Some(match self {
InnerMarker::I64 | InnerMarker::U64 | InnerMarker::F64 => 8,
InnerMarker::I32 | InnerMarker::U32 => 4,
InnerMarker::I16 | InnerMarker::U16 => 2,
InnerMarker::I8 | InnerMarker::U8 | InnerMarker::Bool => 1,
InnerMarker::String | InnerMarker::Object => return None,
})
}
}
/// A marker appended before Epee values which tell you the type of the field and if
/// its a sequence.
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct Marker {
pub inner_marker: InnerMarker,
pub is_seq: bool,
}
impl Marker {
pub(crate) const fn new(inner_marker: InnerMarker) -> Self {
Marker {
inner_marker,
is_seq: false,
}
}
pub const fn into_seq(self) -> Self {
if self.is_seq {
panic!("Sequence of sequence not allowed!");
}
if matches!(self.inner_marker, InnerMarker::U8) {
return Marker {
inner_marker: InnerMarker::String,
is_seq: false,
};
}
Marker {
inner_marker: self.inner_marker,
is_seq: true,
}
}
pub const fn as_u8(&self) -> u8 {
let marker_val = match self.inner_marker {
InnerMarker::I64 => 1,
InnerMarker::I32 => 2,
InnerMarker::I16 => 3,
InnerMarker::I8 => 4,
InnerMarker::U64 => 5,
InnerMarker::U32 => 6,
InnerMarker::U16 => 7,
InnerMarker::U8 => 8,
InnerMarker::F64 => 9,
InnerMarker::String => 10,
InnerMarker::Bool => 11,
InnerMarker::Object => 12,
};
if self.is_seq {
marker_val | 0x80
} else {
marker_val
}
}
}
impl TryFrom<u8> for Marker {
type Error = Error;
fn try_from(mut value: u8) -> Result<Self, Self::Error> {
let is_seq = value & 0x80 > 0;
if is_seq {
value ^= 0x80;
}
let inner_marker = match value {
1 => InnerMarker::I64,
2 => InnerMarker::I32,
3 => InnerMarker::I16,
4 => InnerMarker::I8,
5 => InnerMarker::U64,
6 => InnerMarker::U32,
7 => InnerMarker::U16,
8 => InnerMarker::U8,
9 => InnerMarker::F64,
10 => InnerMarker::String,
11 => InnerMarker::Bool,
12 => InnerMarker::Object,
_ => return Err(Error::Format("Unknown value Marker")),
};
Ok(Marker {
inner_marker,
is_seq,
})
}
}

View file

@ -0,0 +1,511 @@
use alloc::{string::String, vec::Vec};
/// This module contains a `sealed` [`EpeeValue`] trait and different impls for
/// the different possible base epee values.
use core::fmt::Debug;
use bytes::{Buf, BufMut, Bytes};
use sealed::sealed;
use fixed_bytes::{ByteArray, ByteArrayVec};
use crate::{
io::*, varint::*, EpeeObject, Error, InnerMarker, Marker, Result, MAX_STRING_LEN_POSSIBLE,
};
/// A trait for epee values, this trait is sealed as all possible epee values are
/// defined in the lib, to make an [`EpeeValue`] outside the lib you will need to
/// use the trait [`EpeeObject`].
#[sealed]
pub trait EpeeValue: Sized {
const MARKER: Marker;
fn read<B: Buf>(r: &mut B, marker: &Marker) -> Result<Self>;
fn should_write(&self) -> bool {
true
}
/// This is different than default field values and instead is the default
/// value of a whole type.
///
/// For example a `Vec` has a default value of a zero length vec as when a
/// sequence has no entries it is not encoded.
fn epee_default_value() -> Option<Self> {
None
}
fn write<B: BufMut>(self, w: &mut B) -> Result<()>;
}
#[sealed]
impl<T: EpeeObject> EpeeValue for T {
const MARKER: Marker = Marker::new(InnerMarker::Object);
fn read<B: Buf>(r: &mut B, marker: &Marker) -> Result<Self> {
if marker != &Self::MARKER {
return Err(Error::Format("Marker does not match expected Marker"));
}
let mut skipped_objects = 0;
crate::read_object(r, &mut skipped_objects)
}
fn write<B: BufMut>(self, w: &mut B) -> Result<()> {
write_varint(self.number_of_fields(), w)?;
self.write_fields(w)
}
}
#[sealed]
impl<T: EpeeObject> EpeeValue for Vec<T> {
const MARKER: Marker = T::MARKER.into_seq();
fn read<B: Buf>(r: &mut B, marker: &Marker) -> Result<Self> {
if !marker.is_seq {
return Err(Error::Format(
"Marker is not sequence when a sequence was expected",
));
}
let len = read_varint(r)?;
let individual_marker = Marker::new(marker.inner_marker);
let mut res = Vec::with_capacity(len.try_into()?);
for _ in 0..len {
res.push(T::read(r, &individual_marker)?);
}
Ok(res)
}
fn should_write(&self) -> bool {
!self.is_empty()
}
fn epee_default_value() -> Option<Self> {
Some(Vec::new())
}
fn write<B: BufMut>(self, w: &mut B) -> Result<()> {
write_varint(self.len().try_into()?, w)?;
for item in self.into_iter() {
item.write(w)?;
}
Ok(())
}
}
#[sealed]
impl<T: EpeeObject + Debug, const N: usize> EpeeValue for [T; N] {
const MARKER: Marker = <T>::MARKER.into_seq();
fn read<B: Buf>(r: &mut B, marker: &Marker) -> Result<Self> {
let vec = Vec::<T>::read(r, marker)?;
if vec.len() != N {
return Err(Error::Format("Array has incorrect length"));
}
Ok(vec.try_into().unwrap())
}
fn write<B: BufMut>(self, w: &mut B) -> Result<()> {
write_varint(self.len().try_into()?, w)?;
for item in self.into_iter() {
item.write(w)?;
}
Ok(())
}
}
macro_rules! epee_numb {
($numb:ty, $marker:ident, $read_fn:ident, $write_fn:ident) => {
#[sealed]
impl EpeeValue for $numb {
const MARKER: Marker = Marker::new(InnerMarker::$marker);
fn read<B: Buf>(r: &mut B, marker: &Marker) -> Result<Self> {
if marker != &Self::MARKER {
return Err(Error::Format("Marker does not match expected Marker"));
}
checked_read_primitive(r, Buf::$read_fn)
}
fn write<B: BufMut>(self, w: &mut B) -> Result<()> {
checked_write_primitive(w, BufMut::$write_fn, self)
}
}
};
}
epee_numb!(i64, I64, get_i64_le, put_i64_le);
epee_numb!(i32, I32, get_i32_le, put_i32_le);
epee_numb!(i16, I16, get_i16_le, put_i16_le);
epee_numb!(i8, I8, get_i8, put_i8);
epee_numb!(u8, U8, get_u8, put_u8);
epee_numb!(u16, U16, get_u16_le, put_u16_le);
epee_numb!(u32, U32, get_u32_le, put_u32_le);
epee_numb!(u64, U64, get_u64_le, put_u64_le);
epee_numb!(f64, F64, get_f64_le, put_f64_le);
#[sealed]
impl EpeeValue for bool {
const MARKER: Marker = Marker::new(InnerMarker::Bool);
fn read<B: Buf>(r: &mut B, marker: &Marker) -> Result<Self> {
if marker != &Self::MARKER {
return Err(Error::Format("Marker does not match expected Marker"));
}
Ok(checked_read_primitive(r, Buf::get_u8)? != 0)
}
fn write<B: BufMut>(self, w: &mut B) -> Result<()> {
checked_write_primitive(w, BufMut::put_u8, if self { 1 } else { 0 })
}
}
#[sealed]
impl EpeeValue for Vec<u8> {
const MARKER: Marker = Marker::new(InnerMarker::String);
fn read<B: Buf>(r: &mut B, marker: &Marker) -> Result<Self> {
if marker != &Self::MARKER {
return Err(Error::Format("Marker does not match expected Marker"));
}
let len = read_varint(r)?;
if len > MAX_STRING_LEN_POSSIBLE {
return Err(Error::Format("Byte array exceeded max length"));
}
if r.remaining() < len.try_into()? {
return Err(Error::IO("Not enough bytes to fill object"));
}
let mut res = vec![0; len.try_into()?];
r.copy_to_slice(&mut res);
Ok(res)
}
fn write<B: BufMut>(self, w: &mut B) -> Result<()> {
write_varint(self.len().try_into()?, w)?;
if w.remaining_mut() < self.len() {
return Err(Error::IO("Not enough capacity to write bytes"));
}
w.put_slice(&self);
Ok(())
}
}
#[sealed::sealed]
impl EpeeValue for Bytes {
const MARKER: Marker = Marker::new(InnerMarker::String);
fn read<B: Buf>(r: &mut B, marker: &Marker) -> Result<Self> {
if marker != &Self::MARKER {
return Err(Error::Format("Marker does not match expected Marker"));
}
let len = read_varint(r)?;
if len > MAX_STRING_LEN_POSSIBLE {
return Err(Error::Format("Byte array exceeded max length"));
}
if r.remaining() < len.try_into()? {
return Err(Error::IO("Not enough bytes to fill object"));
}
Ok(r.copy_to_bytes(len.try_into()?))
}
fn write<B: BufMut>(self, w: &mut B) -> Result<()> {
write_varint(self.len().try_into()?, w)?;
if w.remaining_mut() < self.len() {
return Err(Error::IO("Not enough capacity to write bytes"));
}
w.put(self);
Ok(())
}
}
#[sealed::sealed]
impl<const N: usize> EpeeValue for ByteArrayVec<N> {
const MARKER: Marker = Marker::new(InnerMarker::String);
fn read<B: Buf>(r: &mut B, marker: &Marker) -> Result<Self> {
if marker != &Self::MARKER {
return Err(Error::Format("Marker does not match expected Marker"));
}
let len = read_varint(r)?;
if len > MAX_STRING_LEN_POSSIBLE {
return Err(Error::Format("Byte array exceeded max length"));
}
if r.remaining()
< usize::try_from(len)?
.checked_mul(N)
.ok_or(Error::Value("Length of field is too long"))?
{
return Err(Error::IO("Not enough bytes to fill object"));
}
ByteArrayVec::try_from(r.copy_to_bytes(usize::try_from(len)?))
.map_err(|_| Error::Format("Field has invalid length"))
}
fn write<B: BufMut>(self, w: &mut B) -> Result<()> {
let bytes = self.take_bytes();
write_varint(bytes.len().try_into()?, w)?;
if w.remaining_mut() < bytes.len() {
return Err(Error::IO("Not enough capacity to write bytes"));
}
w.put(bytes);
Ok(())
}
}
#[sealed::sealed]
impl<const N: usize> EpeeValue for ByteArray<N> {
const MARKER: Marker = Marker::new(InnerMarker::String);
fn read<B: Buf>(r: &mut B, marker: &Marker) -> Result<Self> {
if marker != &Self::MARKER {
return Err(Error::Format("Marker does not match expected Marker"));
}
let len: usize = read_varint(r)?.try_into()?;
if len != N {
return Err(Error::Format("Byte array has incorrect length"));
}
if r.remaining() < N {
return Err(Error::IO("Not enough bytes to fill object"));
}
ByteArray::try_from(r.copy_to_bytes(N))
.map_err(|_| Error::Format("Field has invalid length"))
}
fn write<B: BufMut>(self, w: &mut B) -> Result<()> {
let bytes = self.take_bytes();
write_varint(N.try_into().unwrap(), w)?;
if w.remaining_mut() < N {
return Err(Error::IO("Not enough capacity to write bytes"));
}
w.put(bytes);
Ok(())
}
}
#[sealed]
impl EpeeValue for String {
const MARKER: Marker = Marker::new(InnerMarker::String);
fn read<B: Buf>(r: &mut B, marker: &Marker) -> Result<Self> {
let bytes = Vec::<u8>::read(r, marker)?;
String::from_utf8(bytes).map_err(|_| Error::Format("Invalid string"))
}
fn should_write(&self) -> bool {
!self.is_empty()
}
fn epee_default_value() -> Option<Self> {
Some(String::new())
}
fn write<B: BufMut>(self, w: &mut B) -> Result<()> {
write_varint(self.len().try_into()?, w)?;
if w.remaining_mut() < self.len() {
return Err(Error::IO("Not enough capacity to write bytes"));
}
w.put_slice(self.as_bytes());
Ok(())
}
}
#[sealed]
impl<const N: usize> EpeeValue for [u8; N] {
const MARKER: Marker = Marker::new(InnerMarker::String);
fn read<B: Buf>(r: &mut B, marker: &Marker) -> Result<Self> {
let bytes = Vec::<u8>::read(r, marker)?;
if bytes.len() != N {
return Err(Error::Format("Byte array has incorrect length"));
}
Ok(bytes.try_into().unwrap())
}
fn write<B: BufMut>(self, w: &mut B) -> Result<()> {
write_varint(self.len().try_into()?, w)?;
if w.remaining_mut() < self.len() {
return Err(Error::IO("Not enough capacity to write bytes"));
}
w.put_slice(&self);
Ok(())
}
}
#[sealed]
impl<const N: usize> EpeeValue for Vec<[u8; N]> {
const MARKER: Marker = <[u8; N]>::MARKER.into_seq();
fn read<B: Buf>(r: &mut B, marker: &Marker) -> Result<Self> {
if !marker.is_seq {
return Err(Error::Format(
"Marker is not sequence when a sequence was expected",
));
}
let len = read_varint(r)?;
let individual_marker = Marker::new(marker.inner_marker);
let mut res = Vec::with_capacity(len.try_into()?);
for _ in 0..len {
res.push(<[u8; N]>::read(r, &individual_marker)?);
}
Ok(res)
}
fn should_write(&self) -> bool {
!self.is_empty()
}
fn epee_default_value() -> Option<Self> {
Some(Vec::new())
}
fn write<B: BufMut>(self, w: &mut B) -> Result<()> {
write_varint(self.len().try_into()?, w)?;
for item in self.into_iter() {
item.write(w)?;
}
Ok(())
}
}
macro_rules! epee_seq {
($val:ty) => {
#[sealed]
impl EpeeValue for Vec<$val> {
const MARKER: Marker = <$val>::MARKER.into_seq();
fn read<B: Buf>(r: &mut B, marker: &Marker) -> Result<Self> {
if !marker.is_seq {
return Err(Error::Format(
"Marker is not sequence when a sequence was expected",
));
}
let len = read_varint(r)?;
let individual_marker = Marker::new(marker.inner_marker.clone());
let mut res = Vec::with_capacity(len.try_into()?);
for _ in 0..len {
res.push(<$val>::read(r, &individual_marker)?);
}
Ok(res)
}
fn should_write(&self) -> bool {
!self.is_empty()
}
fn epee_default_value() -> Option<Self> {
Some(Vec::new())
}
fn write<B: BufMut>(self, w: &mut B) -> Result<()> {
write_varint(self.len().try_into()?, w)?;
for item in self.into_iter() {
item.write(w)?;
}
Ok(())
}
}
#[sealed]
impl<const N: usize> EpeeValue for [$val; N] {
const MARKER: Marker = <$val>::MARKER.into_seq();
fn read<B: Buf>(r: &mut B, marker: &Marker) -> Result<Self> {
let vec = Vec::<$val>::read(r, marker)?;
if vec.len() != N {
return Err(Error::Format("Array has incorrect length"));
}
Ok(vec.try_into().unwrap())
}
fn write<B: BufMut>(self, w: &mut B) -> Result<()> {
write_varint(self.len().try_into()?, w)?;
for item in self.into_iter() {
item.write(w)?;
}
Ok(())
}
}
};
}
epee_seq!(i64);
epee_seq!(i32);
epee_seq!(i16);
epee_seq!(i8);
epee_seq!(u64);
epee_seq!(u32);
epee_seq!(u16);
epee_seq!(f64);
epee_seq!(bool);
epee_seq!(Vec<u8>);
epee_seq!(String);
#[sealed]
impl<T: EpeeValue> EpeeValue for Option<T> {
const MARKER: Marker = T::MARKER;
fn read<B: Buf>(r: &mut B, marker: &Marker) -> Result<Self> {
Ok(Some(T::read(r, marker)?))
}
fn should_write(&self) -> bool {
match self {
Some(t) => t.should_write(),
None => false,
}
}
fn epee_default_value() -> Option<Self> {
Some(None)
}
fn write<B: BufMut>(self, w: &mut B) -> Result<()> {
match self {
Some(t) => t.write(w)?,
None => panic!("Can't write an Option::None value, this should be handled elsewhere"),
}
Ok(())
}
}

View file

@ -0,0 +1,91 @@
use bytes::{Buf, BufMut};
use crate::error::*;
const SIZE_OF_SIZE_MARKER: u32 = 2;
const FITS_IN_ONE_BYTE: u64 = 2_u64.pow(8 - SIZE_OF_SIZE_MARKER) - 1;
const FITS_IN_TWO_BYTES: u64 = 2_u64.pow(16 - SIZE_OF_SIZE_MARKER) - 1;
const FITS_IN_FOUR_BYTES: u64 = 2_u64.pow(32 - SIZE_OF_SIZE_MARKER) - 1;
pub fn read_varint<B: Buf>(r: &mut B) -> Result<u64> {
if !r.has_remaining() {
Err(Error::IO("Not enough bytes to build VarInt"))?
}
let vi_start = r.get_u8();
let len = 1 << (vi_start & 0b11);
if r.remaining() < len - 1 {
Err(Error::IO("Not enough bytes to build VarInt"))?
}
let mut vi = u64::from(vi_start >> 2);
for i in 1..len {
vi |= u64::from(r.get_u8()) << (((i - 1) * 8) + 6);
}
Ok(vi)
}
pub fn write_varint<B: BufMut>(number: u64, w: &mut B) -> Result<()> {
let size_marker = match number {
0..=FITS_IN_ONE_BYTE => 0,
64..=FITS_IN_TWO_BYTES => 1,
16384..=FITS_IN_FOUR_BYTES => 2,
_ => 3,
};
if w.remaining_mut() < 1 << size_marker {
Err(Error::IO("Not enough capacity to write VarInt"))?;
}
let number = (number << 2) | size_marker;
// Although `as` is unsafe we just checked the length.
match size_marker {
0 => w.put_u8(number as u8),
1 => w.put_u16_le(number as u16),
2 => w.put_u32_le(number as u32),
3 => w.put_u64_le(number),
_ => unreachable!(),
}
Ok(())
}
#[cfg(test)]
mod tests {
use alloc::vec::Vec;
use crate::varint::*;
fn assert_varint_length(number: u64, len: usize) {
let mut w = Vec::new();
write_varint(number, &mut w).unwrap();
assert_eq!(w.len(), len);
}
fn assert_varint_val(mut varint: &[u8], val: u64) {
assert_eq!(read_varint(&mut varint).unwrap(), val);
}
#[test]
fn varint_write_length() {
assert_varint_length(FITS_IN_ONE_BYTE, 1);
assert_varint_length(FITS_IN_ONE_BYTE + 1, 2);
assert_varint_length(FITS_IN_TWO_BYTES, 2);
assert_varint_length(FITS_IN_TWO_BYTES + 1, 4);
assert_varint_length(FITS_IN_FOUR_BYTES, 4);
assert_varint_length(FITS_IN_FOUR_BYTES + 1, 8);
}
#[test]
fn varint_read() {
assert_varint_val(&[252], FITS_IN_ONE_BYTE);
assert_varint_val(&[1, 1], FITS_IN_ONE_BYTE + 1);
assert_varint_val(&[253, 255], FITS_IN_TWO_BYTES);
assert_varint_val(&[2, 0, 1, 0], FITS_IN_TWO_BYTES + 1);
assert_varint_val(&[254, 255, 255, 255], FITS_IN_FOUR_BYTES);
assert_varint_val(&[3, 0, 0, 0, 1, 0, 0, 0], FITS_IN_FOUR_BYTES + 1);
}
}

View file

@ -0,0 +1,35 @@
use epee_encoding::{epee_object, from_bytes, to_bytes};
struct AltName {
val: u8,
d: u64,
}
epee_object!(
AltName,
val("val2"): u8,
d: u64,
);
struct AltName2 {
val2: u8,
d: u64,
}
epee_object!(
AltName2,
val2: u8,
d: u64,
);
#[test]
fn epee_alt_name() {
let val2 = AltName2 { val2: 40, d: 30 };
let bytes = to_bytes(val2).unwrap();
let val: AltName = from_bytes(&bytes).unwrap();
let bytes2 = to_bytes(val).unwrap();
assert_eq!(bytes, bytes2);
}

View file

@ -0,0 +1,39 @@
use epee_encoding::{epee_object, from_bytes};
struct T {
a: u8,
}
epee_object!(
T,
a: u8,
);
struct TT {
a: u8,
}
epee_object!(
TT,
a: u8 = 0,
);
#[test]
fn duplicate_key() {
let data = [
0x01, 0x11, 0x01, 0x1, 0x01, 0x01, 0x02, 0x1, 0x1, 0x08, 0x01, b'a', 0x0B, 0x00, 0x01,
b'a', 0x0B, 0x00,
];
assert!(from_bytes::<T>(&data).is_err());
}
#[test]
fn duplicate_key_with_default() {
let data = [
0x01, 0x11, 0x01, 0x1, 0x01, 0x01, 0x02, 0x1, 0x1, 0x08, 0x01, b'a', 0x0B, 0x00, 0x01,
b'a', 0x0B, 0x00,
];
assert!(from_bytes::<TT>(&data).is_err());
}

View file

@ -0,0 +1,74 @@
use epee_encoding::{epee_object, from_bytes, to_bytes};
pub struct Optional {
val: u8,
optional_val: i32,
}
epee_object!(
Optional,
val: u8,
optional_val: i32 = -4,
);
pub struct NotOptional {
val: u8,
optional_val: i32,
}
epee_object!(
NotOptional,
val: u8,
optional_val: i32,
);
#[derive(Default)]
pub struct NotPresent {
val: u8,
}
epee_object!(
NotPresent,
val: u8,
);
#[test]
fn epee_default_does_not_encode() {
let val = Optional {
val: 1,
optional_val: -4,
};
let bytes = to_bytes(val).unwrap();
assert!(from_bytes::<NotOptional>(&bytes).is_err());
let val: Optional = from_bytes(&bytes).unwrap();
assert_eq!(val.optional_val, -4);
assert_eq!(val.val, 1);
}
#[test]
fn epee_non_default_does_encode() {
let val = Optional {
val: 8,
optional_val: -3,
};
let bytes = to_bytes(val).unwrap();
assert!(from_bytes::<NotOptional>(&bytes).is_ok());
let val: Optional = from_bytes(&bytes).unwrap();
assert_eq!(val.optional_val, -3);
assert_eq!(val.val, 8)
}
#[test]
fn epee_value_not_present_with_default() {
let val = NotPresent { val: 76 };
let bytes = to_bytes(val).unwrap();
assert!(from_bytes::<NotOptional>(&bytes).is_err());
let val: Optional = from_bytes(&bytes).unwrap();
assert_eq!(val.optional_val, -4);
assert_eq!(val.val, 76)
}

View file

@ -0,0 +1,102 @@
use epee_encoding::{epee_object, from_bytes, to_bytes};
struct Child {
val: u64,
val2: Vec<u8>,
}
epee_object!(
Child,
val: u64,
val2: Vec<u8>,
);
struct Parent {
child: Child,
h: f64,
}
epee_object!(
Parent,
h: f64,
!flatten:
child: Child,
);
#[derive(Clone)]
struct ParentChild {
h: f64,
val: u64,
val2: Vec<u8>,
}
epee_object!(
ParentChild,
h: f64,
val: u64,
val2: Vec<u8>,
);
#[test]
fn epee_flatten() {
let val2 = ParentChild {
h: 38.9,
val: 94,
val2: vec![4, 5],
};
let bytes = to_bytes(val2.clone()).unwrap();
let val: Parent = from_bytes(&bytes).unwrap();
assert_eq!(val.child.val2, val2.val2);
assert_eq!(val.child.val, val2.val);
assert_eq!(val.h, val2.h);
}
#[derive(Debug, Default, Clone, PartialEq)]
struct Child1 {
val: u64,
val2: Vec<u8>,
}
epee_object!(
Child1,
val: u64,
val2: Vec<u8>,
);
#[derive(Debug, Default, Clone, PartialEq)]
struct Child2 {
buz: u16,
fiz: String,
}
epee_object!(
Child2,
buz: u16,
fiz: String,
);
#[derive(Debug, Default, Clone, PartialEq)]
struct Parent12 {
child1: Child1,
child2: Child2,
h: f64,
}
epee_object!(
Parent12,
h: f64,
!flatten:
child1: Child1,
child2: Child2,
);
#[test]
fn epee_double_flatten() {
let val = Parent12::default();
let bytes = to_bytes(val.clone()).unwrap();
let val1: Parent12 = from_bytes(&bytes).unwrap();
assert_eq!(val, val1);
}

View file

@ -0,0 +1,31 @@
use epee_encoding::{epee_object, from_bytes, to_bytes};
#[derive(Clone)]
struct T {
val: Option<u8>,
}
epee_object!(
T,
val: Option<u8>,
);
#[test]
fn optional_val_not_in_data() {
let bytes: &[u8] = b"\x01\x11\x01\x01\x01\x01\x02\x01\x01\x00";
let t: T = from_bytes(bytes).unwrap();
let bytes2 = to_bytes(t.clone()).unwrap();
assert_eq!(bytes, bytes2);
assert!(t.val.is_none());
}
#[test]
fn optional_val_in_data() {
let bytes = [
0x01, 0x11, 0x01, 0x1, 0x01, 0x01, 0x02, 0x1, 0x1, 0x04, 0x03, b'v', b'a', b'l', 0x08, 21,
];
let t: T = from_bytes(&bytes).unwrap();
let bytes2 = to_bytes(t.clone()).unwrap();
assert_eq!(bytes.as_slice(), bytes2.as_slice());
assert_eq!(t.val.unwrap(), 21);
}

View file

@ -0,0 +1,59 @@
use epee_encoding::{epee_object, from_bytes, to_bytes};
#[derive(Eq, PartialEq, Debug, Clone)]
pub struct SupportFlags(u32);
impl From<u32> for SupportFlags {
fn from(value: u32) -> Self {
SupportFlags(value)
}
}
impl From<SupportFlags> for u32 {
fn from(value: SupportFlags) -> Self {
value.0
}
}
impl<'a> From<&'a SupportFlags> for &'a u32 {
fn from(value: &'a SupportFlags) -> Self {
&value.0
}
}
#[derive(Eq, PartialEq, Debug, Clone)]
pub struct BasicNodeData {
pub my_port: u32,
pub network_id: [u8; 16],
pub peer_id: u64,
pub support_flags: SupportFlags,
}
epee_object!(
BasicNodeData,
my_port: u32,
network_id: [u8; 16],
peer_id: u64,
support_flags: SupportFlags as u32,
);
#[derive(Eq, PartialEq, Debug, Clone)]
pub struct HandshakeR {
pub node_data: BasicNodeData,
}
epee_object!(
HandshakeR,
node_data: BasicNodeData,
);
#[test]
fn p2p_handshake() {
let bytes = hex::decode("01110101010102010108096e6f64655f646174610c10076d795f706f727406a04600000a6e6574776f726b5f69640a401230f171610441611731008216a1a11007706565725f6964053eb3c096c4471c340d737570706f72745f666c61677306010000000c7061796c6f61645f646174610c181563756d756c61746976655f646966666963756c7479053951f7a79aab4a031b63756d756c61746976655f646966666963756c74795f746f7036340500000000000000000e63757272656e745f68656967687405fa092a00000000000c7072756e696e675f73656564068001000006746f705f69640a806cc497b230ba57a95edb370be8d6870c94e0992937c89b1def3a4cb7726d37ad0b746f705f76657273696f6e0810").unwrap();
let val: HandshakeR = from_bytes(&bytes).unwrap();
let bytes = to_bytes(val.clone()).unwrap();
assert_eq!(val, from_bytes(&bytes).unwrap());
}

View file

@ -0,0 +1,83 @@
use epee_encoding::{epee_object, from_bytes, to_bytes};
#[derive(Clone, Debug, PartialEq)]
struct BaseResponse {
credits: u64,
status: String,
top_hash: String,
untrusted: bool,
}
epee_object!(
BaseResponse,
credits: u64,
status: String,
top_hash: String,
untrusted: bool,
);
#[derive(Clone, Debug, PartialEq)]
struct GetOIndexesResponse {
base: BaseResponse,
o_indexes: Vec<u64>,
}
epee_object!(
GetOIndexesResponse,
o_indexes: Vec<u64>,
!flatten:
base: BaseResponse,
);
#[derive(Clone, Debug, PartialEq)]
struct GetOutsResponse {
base: BaseResponse,
outs: Vec<OutKey>,
}
epee_object!(
GetOutsResponse,
outs: Vec<OutKey>,
!flatten:
base: BaseResponse,
);
#[derive(Clone, Copy, Debug, PartialEq)]
struct OutKey {
height: u64,
key: [u8; 32],
mask: [u8; 32],
txid: [u8; 32],
unlocked: bool,
}
epee_object!(
OutKey,
height: u64,
key: [u8; 32],
mask: [u8; 32],
txid: [u8; 32],
unlocked: bool,
);
#[test]
fn rpc_get_outs_response() {
let bytes = hex::decode("011101010101020101140763726564697473050000000000000000046f7574738c04140668656967687405a100000000000000036b65790a802d392d0be38eb4699c17767e62a063b8d2f989ec15c80e5d2665ab06f8397439046d61736b0a805e8b863c5b267deda13f4bc5d5ec8e59043028380f2431bc8691c15c83e1fea404747869640a80c0646e065a33b849f0d9563673ca48eb0c603fe721dd982720dba463172c246f08756e6c6f636b65640b00067374617475730a084f4b08746f705f686173680a0009756e747275737465640b00").unwrap();
let val: GetOutsResponse = from_bytes(&bytes).unwrap();
let bytes = to_bytes(val.clone()).unwrap();
assert_eq!(val, from_bytes(&bytes).unwrap());
}
#[test]
fn get_out_indexes_response() {
let bytes = [
1, 17, 1, 1, 1, 1, 2, 1, 1, 16, 7, 99, 114, 101, 100, 105, 116, 115, 5, 0, 0, 0, 0, 0, 0,
0, 0, 6, 115, 116, 97, 116, 117, 115, 10, 8, 79, 75, 8, 116, 111, 112, 95, 104, 97, 115,
104, 10, 0, 9, 117, 110, 116, 114, 117, 115, 116, 101, 100, 11, 0,
];
let val: GetOIndexesResponse = from_bytes(&bytes).unwrap();
let bytes = to_bytes(val.clone()).unwrap();
assert_eq!(val, from_bytes(&bytes).unwrap());
}

View file

@ -0,0 +1,60 @@
use epee_encoding::{epee_object, from_bytes};
struct ObjSeq {
seq: Vec<ObjSeq>,
}
epee_object!(
ObjSeq,
seq: Vec<ObjSeq>,
);
struct ValSeq {
seq: Vec<i64>,
}
epee_object!(
ValSeq,
seq: Vec<i64>,
);
#[test]
fn seq_with_zero_len_can_have_any_marker() {
let mut data = [
0x01, 0x11, 0x01, 0x1, 0x01, 0x01, 0x02, 0x1, 0x1, 0x04, 0x03, b's', b'e', b'q',
]
.to_vec();
for marker in 1..13 {
data.push(0x80 | marker);
data.push(0);
assert!(from_bytes::<ObjSeq>(&data).is_ok());
assert!(from_bytes::<ValSeq>(&data).is_ok());
data.drain(14..);
}
}
#[test]
fn seq_with_non_zero_len_must_have_correct_marker() {
let mut data = [
0x01, 0x11, 0x01, 0x1, 0x01, 0x01, 0x02, 0x1, 0x1, 0x04, 0x03, b's', b'e', b'q',
]
.to_vec();
for marker in 2..13 {
// 1 is the marker for i64
data.push(0x80 | marker);
data.push(0x04); // varint length of 1
data.extend_from_slice(&1_i64.to_le_bytes());
assert!(from_bytes::<ValSeq>(&data).is_err());
data.drain(14..);
}
data.push(0x80 + 1);
data.push(0x04); // varint length
data.extend_from_slice(&1_i64.to_le_bytes());
(from_bytes::<ValSeq>(&data).unwrap());
}

View file

@ -0,0 +1,741 @@
use epee_encoding::{epee_object, from_bytes};
struct D {
val: u8,
}
epee_object!(
D,
val: u8,
);
struct Q {
req: u8,
d: D,
}
epee_object!(
Q,
req: u8,
d: D,
);
#[test]
fn stack_overlfow() {
let bytes = vec![
1, 17, 1, 1, 1, 1, 2, 1, 1, 8, 3, 114, 101, 113, 8, 3, 1, 100, 12, 8, 3, 118, 97, 108, 8,
7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12,
8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97,
108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1,
100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3,
118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108,
8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100,
12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118,
97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7,
1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8,
3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97,
108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1,
100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3,
118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108,
8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100,
12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118,
97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7,
1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8,
3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97,
108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1,
100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3,
118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108,
8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100,
12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118,
97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7,
1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8,
3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97,
108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1,
100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3,
118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108,
8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100,
12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118,
97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7,
1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8,
3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97,
108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1,
100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3,
118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108,
8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100,
12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118,
97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7,
1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8,
3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97,
108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1,
100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3,
118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108,
8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100,
12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118,
97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7,
1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8,
3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97,
108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1,
100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3,
118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108,
8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100,
12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118,
97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7,
1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8,
3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97,
108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1,
100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3,
118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108,
8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100,
12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118,
97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7,
1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8,
3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97,
108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1,
100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3,
118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108,
8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100,
12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118,
97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7,
1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8,
3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97,
108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1,
100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3,
118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108,
8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100,
12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118,
97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7,
1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8,
3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97,
108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1,
100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3,
118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108,
8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100,
12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118,
97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7,
1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8,
3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97,
108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1,
100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3,
118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108,
8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100,
12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118,
97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7,
1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8,
3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97,
108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1,
100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3,
118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108,
8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100,
12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118,
97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7,
1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8,
3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97,
108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1,
100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3,
118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108,
8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100,
12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118,
97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7,
1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8,
3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97,
108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1,
100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3,
118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108,
8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100,
12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118,
97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7,
1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8,
3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97,
108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1,
100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3,
118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108,
8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100,
12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118,
97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7,
1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8,
3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97,
108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1,
100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3,
118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108,
8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100,
12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118,
97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7,
1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8,
3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97,
108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1,
100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3,
118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108,
8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100,
12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118,
97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7,
1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8,
3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97,
108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1,
100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3,
118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108,
8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100,
12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118,
97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7,
1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8,
3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97,
108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1,
100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3,
118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108,
8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100,
12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118,
97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7,
1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8,
3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97,
108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1,
100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3,
118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108,
8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100,
12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118,
97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7,
1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8,
3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97,
108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1,
100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3,
118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108,
8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100,
12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118,
97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7,
1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8,
3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97,
108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1,
100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3,
118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108,
8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100,
12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118,
97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7,
1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8,
3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97,
108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1,
100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3,
118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108,
8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100,
12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118,
97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7,
1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8,
3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97,
108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1,
100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3,
118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108,
8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100,
12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118,
97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7,
1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8,
3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97,
108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1,
100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3,
118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108,
8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100,
12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118,
97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7,
1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8,
3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97,
108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1,
100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3,
118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108,
8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100,
12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118,
97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7,
1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8,
3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97,
108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1,
100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3,
118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108,
8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100,
12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118,
97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7,
1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8,
3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97,
108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1,
100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3,
118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108,
8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100,
12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118,
97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7,
1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8,
3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97,
108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1,
100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3,
118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108,
8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100,
12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118,
97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7,
1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8,
3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97,
108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1,
100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3,
118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108,
8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100,
12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118,
97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7,
1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8,
3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97,
108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1,
100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3,
118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108,
8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100,
12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118,
97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7,
1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8,
3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97,
108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1,
100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3,
118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108,
8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100,
12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118,
97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7,
1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8,
3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97,
108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1,
100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3,
118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108,
8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100,
12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118,
97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7,
1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8,
3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97,
108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1,
100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3,
118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108,
8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100,
12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118,
97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7,
1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8,
3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97,
108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1,
100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3,
118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108,
8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100,
12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118,
97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7,
1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8,
3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97,
108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1,
100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3,
118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108,
8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100,
12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118,
97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7,
1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8,
3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97,
108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1,
100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3,
118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108,
8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100,
12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118,
97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7,
1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8,
3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97,
108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1,
100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3,
118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108,
8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100,
12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118,
97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7,
1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8,
3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97,
108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1,
100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3,
118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108,
8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100,
12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118,
97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7,
1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8,
3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97,
108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1,
100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3,
118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108,
8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100,
12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118,
97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7,
1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8,
3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97,
108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1,
100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3,
118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108,
8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100,
12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118,
97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7,
1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8,
3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97,
108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1,
100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3,
118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108,
8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100,
12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118,
97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7,
1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8,
3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97,
108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1,
100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3,
118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108,
8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100,
12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118,
97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7,
1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8,
3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97,
108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1,
100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3,
118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108,
8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100,
12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118,
97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7,
1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8,
3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97,
108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1,
100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3,
118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108,
8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100,
12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118,
97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7,
1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8,
3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97,
108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1,
100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3,
118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108,
8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100,
12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118,
97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7,
1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8,
3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97,
108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1,
100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3,
118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108,
8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100,
12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118,
97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7,
1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8,
3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97,
108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1,
100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3,
118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108,
8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100,
12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118,
97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7,
1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8,
3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97,
108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1,
100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3,
118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108,
8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100,
12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118,
97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7,
1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8,
3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97,
108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1,
100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3,
118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108,
8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100,
12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118,
97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7,
1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8,
3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97,
108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1,
100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3,
118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108,
8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100,
12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118,
97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7,
1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8,
3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97,
108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1,
100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3,
118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108,
8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100,
12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118,
97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7,
1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8,
3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97,
108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1,
100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3,
118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108,
8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100,
12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118,
97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7,
1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8,
3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97,
108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1,
100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3,
118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108,
8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100,
12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118,
97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7,
1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8,
3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97,
108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1,
100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3,
118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108,
8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100,
12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118,
97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7,
1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8,
3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97,
108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1,
100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3,
118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108,
8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100,
12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118,
97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7,
1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8,
3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97,
108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1,
100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3,
118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108,
8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100,
12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118,
97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7,
1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8,
3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97,
108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1,
100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3,
118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108,
8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100,
12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118,
97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7,
1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8,
3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97,
108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1,
100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3,
118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108,
8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100,
12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118,
97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7,
1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8,
3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97,
108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1,
100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3,
118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108,
8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100,
12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118,
97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7,
1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8,
3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97,
108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1,
100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3,
118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108,
8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100,
12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118,
97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7,
1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8,
3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97,
108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1,
100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3,
118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108,
8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100,
12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118,
97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7,
1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8,
3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97,
108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1,
100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3,
118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108,
8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100,
12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118,
97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7,
1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8,
3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97,
108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1,
100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3,
118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108,
8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100,
12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118,
97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7,
1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8,
3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97,
108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1,
100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3,
118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108,
8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100,
12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118,
97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7,
1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8,
3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97,
108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1,
100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3,
118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108,
8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100,
12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118,
97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7,
1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8,
3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97,
108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1,
100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3,
118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108,
8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100,
12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118,
97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7,
1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8,
3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97,
108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1,
100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3,
118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108,
8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100,
12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118,
97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7,
1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8,
3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97,
108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1,
100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3,
118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108,
8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100,
12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118,
97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7,
1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8,
3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97,
108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1,
100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3,
118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108,
8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100,
12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118,
97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7,
1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8,
3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97,
108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1,
100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3,
118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108,
8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100,
12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118,
97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7,
1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8,
3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97,
108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1,
100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3,
118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108,
8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100,
12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118,
97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7,
1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8,
3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97,
108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1,
100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3,
118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108,
8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100,
12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118,
97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7,
1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8,
3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97,
108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1,
100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3,
118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108,
8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100,
12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118,
97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7,
1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8,
3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97,
108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1,
100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3,
118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108,
8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100,
12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118,
97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7,
1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8,
3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97,
108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1,
100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3,
118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108,
8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100,
12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118,
97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7,
1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8,
3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97,
108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1,
100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3,
118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108,
8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100,
12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118,
97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7,
1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8,
3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97,
108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1,
100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3,
118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108,
8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100,
12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118,
97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7,
1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8,
3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97,
108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1,
100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3,
118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108,
8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100,
12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118,
97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7,
1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8,
3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97,
108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1,
100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3,
118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108,
8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100,
12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118,
97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7,
1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8,
3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97,
108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1,
100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3,
118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108,
8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100,
12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118,
97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7,
1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8,
3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97,
108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1,
100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3,
118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108,
8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100,
12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118,
97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7,
1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8,
3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97,
108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1,
100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3,
118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108,
8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100,
12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118,
97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7,
1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8,
3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97,
108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1,
100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3,
118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108,
8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100,
12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118,
97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7,
1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8,
3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97,
108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1,
100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3,
118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108,
8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100,
12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118,
97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7,
1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8,
3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97,
108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1,
100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3,
118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108,
8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100,
12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118,
97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7,
1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8,
3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97,
108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1,
100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3,
118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108,
8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100,
12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118,
97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7,
1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8,
3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97,
108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1,
100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3,
118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7, 1, 100, 12, 8, 3, 118, 97, 108,
8, 7, 1, 100, 12, 8, 3, 118, 97, 108, 8, 7,
];
let obj: Result<Q, _> = from_bytes(&bytes);
assert!(obj.is_err())
}

View file

@ -0,0 +1,12 @@
[package]
name = "fixed-bytes"
version = "0.1.0"
edition = "2021"
[features]
default = ["std"]
std = ["bytes/std", "dep:thiserror"]
[dependencies]
thiserror = { workspace = true, optional = true }
bytes = { workspace = true }

126
net/fixed-bytes/src/lib.rs Normal file
View file

@ -0,0 +1,126 @@
use core::ops::Deref;
use std::fmt::{Debug, Formatter};
use std::ops::Index;
use bytes::Bytes;
#[cfg_attr(feature = "std", derive(thiserror::Error))]
pub enum FixedByteError {
#[cfg_attr(
feature = "std",
error("Cannot create fix byte array, input has invalid length.")
)]
InvalidLength,
}
impl FixedByteError {
fn field_name(&self) -> &'static str {
match self {
FixedByteError::InvalidLength => "input",
}
}
fn field_data(&self) -> &'static str {
match self {
FixedByteError::InvalidLength => {
"Cannot create fix byte array, input has invalid length."
}
}
}
}
impl Debug for FixedByteError {
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
f.debug_struct("FixedByteError")
.field(self.field_name(), &self.field_data())
.finish()
}
}
/// A fixed size byte slice.
///
/// Internally this is just a wrapper around [`Bytes`], with the constructors checking that the length is equal to [`N`].
/// This implements [`Deref`] with the target being `[u8; N]`.
pub struct ByteArray<const N: usize>(Bytes);
impl<const N: usize> ByteArray<N> {
pub fn take_bytes(self) -> Bytes {
self.0
}
}
impl<const N: usize> Deref for ByteArray<N> {
type Target = [u8; N];
fn deref(&self) -> &Self::Target {
self.0.deref().try_into().unwrap()
}
}
impl<const N: usize> TryFrom<Bytes> for ByteArray<N> {
type Error = FixedByteError;
fn try_from(value: Bytes) -> Result<Self, Self::Error> {
if value.len() != N {
return Err(FixedByteError::InvalidLength);
}
Ok(ByteArray(value))
}
}
pub struct ByteArrayVec<const N: usize>(Bytes);
impl<const N: usize> ByteArrayVec<N> {
pub fn len(&self) -> usize {
self.0.len() / N
}
pub fn is_empty(&self) -> bool {
self.len() == 0
}
pub fn take_bytes(self) -> Bytes {
self.0
}
}
impl<const N: usize> TryFrom<Bytes> for ByteArrayVec<N> {
type Error = FixedByteError;
fn try_from(value: Bytes) -> Result<Self, Self::Error> {
if value.len() % N != 0 {
return Err(FixedByteError::InvalidLength);
}
Ok(ByteArrayVec(value))
}
}
impl<const N: usize> Index<usize> for ByteArrayVec<N> {
type Output = [u8; 32];
fn index(&self, index: usize) -> &Self::Output {
if (index + 1) * N > self.0.len() {
panic!("Index out of range, idx: {}, length: {}", index, self.len());
}
self.0[index * N..(index + 1) * N]
.as_ref()
.try_into()
.unwrap()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn byte_array_vec_len() {
let bytes = vec![0; 32 * 100];
let bytes = ByteArrayVec::<32>::try_from(Bytes::from(bytes)).unwrap();
assert_eq!(bytes.len(), 100);
let _ = bytes[99];
}
}

View file

@ -8,7 +8,7 @@ authors = ["Boog900"]
repository = "https://github.com/Cuprate/cuprate/tree/main/net/levin"
[dependencies]
thiserror = "1"
bytes = "1"
tokio-util = {version = "0.7", features = ["codec"]}
thiserror = { workspace = true }
bytes = { workspace = true }
tokio-util = { workspace = true, features = ["codec"]}