mirror of
https://github.com/hinto-janai/cuprate.git
synced 2024-12-22 11:39:30 +00:00
net: add epee-encoding and fixed-bytes
This commit is contained in:
parent
1b8bfb8a32
commit
2b65be4b18
25 changed files with 2973 additions and 91 deletions
38
Cargo.lock
generated
38
Cargo.lock
generated
|
@ -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"
|
||||
|
|
|
@ -6,6 +6,8 @@ members = [
|
|||
"consensus/rules",
|
||||
"cryptonight",
|
||||
"helper",
|
||||
"net/epee-encoding",
|
||||
"net/fixed-bytes",
|
||||
"net/levin",
|
||||
"net/monero-wire",
|
||||
"p2p/monero-p2p",
|
||||
|
|
147
misc/DESIGN.md
147
misc/DESIGN.md
|
@ -20,16 +20,16 @@
|
|||
|
||||
### Introduction
|
||||
|
||||
This document outlines the initial plan for Cuprate, a Rust Monero node. Currently, Monero only
|
||||
This document outlines the initial plan for Cuprate, a Rust Monero node. Currently, Monero only
|
||||
has one node implementation, which many would class as an issue.
|
||||
|
||||
This document isn't supposed to outline everything, but it is meant to give a good overview of the
|
||||
This document isn't supposed to outline everything, but it is meant to give a good overview of the
|
||||
plan.
|
||||
|
||||
Cuprate won't build everything from scratch and aims to use crates already in existence
|
||||
when they're a good fit, an example is monero-serai for our transactions and blocks.
|
||||
when they're a good fit, an example is monero-serai for our transactions and blocks.
|
||||
|
||||
Cuprate makes heavy use of [tower](https://docs.rs/tower/latest/tower/index.html) to modularize its
|
||||
Cuprate makes heavy use of [tower](https://docs.rs/tower/latest/tower/index.html) to modularize its
|
||||
parts. Using tower across the node will provide us with a consistent API and will allow us to use towers
|
||||
extensive middleware, for tasks such as routing requests and timeouts.
|
||||
|
||||
|
@ -38,49 +38,57 @@ extensive middleware, for tasks such as routing requests and timeouts.
|
|||
### P2P
|
||||
|
||||
Cuprates P2P takes heavy inspiration from Zebra. The P2P crate will abstract the network into one endpoint,
|
||||
meaning other parts of the node will have no P2P code except from sending requests to this one endpoint.
|
||||
This endpoint will be made of a few different tower::Services for the different routing methods, the most
|
||||
meaning other parts of the node will have no P2P code except from sending requests to this one endpoint.
|
||||
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. |
|
||||
| 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`. |
|
||||
| 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
|
||||
|
||||
This library will have the [levin header format](https://github.com/monero-project/monero/blob/master/docs/LEVIN_PROTOCOL.md#header),
|
||||
with a [tokio-codec](https://docs.rs/tokio-util/0.7.8/tokio_util/codec/index.html) for encoding and
|
||||
decoding p2p messages. To do this a trait `LevinMessage` will be used so users can define their own
|
||||
with a [tokio-codec](https://docs.rs/tokio-util/0.7.8/tokio_util/codec/index.html) for encoding and
|
||||
decoding p2p messages. To do this a trait `LevinMessage` will be used so users can define their own
|
||||
P2P messages. This will allow other Rust projects to use the levin header format with different messages.
|
||||
|
||||
#### monero-wire
|
||||
|
||||
This will be a library built on top of [levin-cuprate](#levin-cuprate), It will contain every P2P
|
||||
This will be a library built on top of [levin-cuprate](#levin-cuprate), It will contain every P2P
|
||||
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.
|
||||
The serialization format used for P2P messages has already been implemented in Rust, multiple times :). I have decided to
|
||||
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
|
||||
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.
|
||||
|
||||
---
|
||||
|
||||
|
@ -142,7 +141,7 @@ for the different routing methods:
|
|||
|
||||
The verifier will be split into 2 different tower::Services: block and transaction. All checks will
|
||||
be explicit and won't be scattered around the codebase, if for some reason we do have to scatter checks
|
||||
(some are preformed at de-serialisation for example) they will be referred to in to in the non-scattered
|
||||
(some are preformed at de-serialisation for example) they will be referred to in to in the non-scattered
|
||||
location.
|
||||
|
||||
The verifiers tower::Services will be optional and behind a feature flags so projects that need Monero's consensus
|
||||
|
@ -158,50 +157,22 @@ old CryptoNight POW(s).
|
|||
|
||||
#### Transaction
|
||||
|
||||
Responsible for validating transactions. This is able to handle one or more transactions at a time to
|
||||
benefit from batching verification where we can, currently only bulletproofs(+) is able to be batched.
|
||||
monero-serai already has the API to allow batch verification of bulletproofs(+). Also accepting multiple
|
||||
transactions will also allow us to use a thread-pool like `rayon` to parallelize verification that can't
|
||||
Responsible for validating transactions. This is able to handle one or more transactions at a time to
|
||||
benefit from batching verification where we can, currently only bulletproofs(+) is able to be batched.
|
||||
monero-serai already has the API to allow batch verification of bulletproofs(+). Also accepting multiple
|
||||
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
|
||||
|
||||
The database interface will abstract away the underlying database to allow us to easily swap out the database for a different one,
|
||||
this makes it possible to performance test different databases for our workload, which we plan to do. Initially we plan to go with
|
||||
this makes it possible to performance test different databases for our workload, which we plan to do. Initially we plan to go with
|
||||
MDBX, a database similar to LMDB which is used in monerod.
|
||||
|
||||
We plan to investigate the database schema for optimisations as well, so our schema will more than likely be different than monerods.
|
||||
We plan to investigate the database schema for optimisations as well, so our schema will more than likely be different than monerods.
|
||||
|
||||
Cuprate will interact with the database though a tower::Service providing another layer of abstraction, the service will make use of
|
||||
the database interface abstraction. This allows us to make use of towers middleware for the database and makes the database conform to
|
||||
Cuprate will interact with the database though a tower::Service providing another layer of abstraction, the service will make use of
|
||||
the database interface abstraction. This allows us to make use of towers middleware for the database and makes the database conform to
|
||||
the API of the rest of the node.
|
||||
|
|
26
net/epee-encoding/Cargo.toml
Normal file
26
net/epee-encoding/Cargo.toml
Normal 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
21
net/epee-encoding/LICENSE
Normal 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
202
net/epee-encoding/README.md
Normal 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>,
|
||||
}
|
||||
```
|
52
net/epee-encoding/src/error.rs
Normal file
52
net/epee-encoding/src/error.rs
Normal 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")
|
||||
}
|
||||
}
|
44
net/epee-encoding/src/io.rs
Normal file
44
net/epee-encoding/src/io.rs
Normal 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(())
|
||||
}
|
317
net/epee-encoding/src/lib.rs
Normal file
317
net/epee-encoding/src/lib.rs
Normal 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)
|
||||
}
|
125
net/epee-encoding/src/macros.rs
Normal file
125
net/epee-encoding/src/macros.rs
Normal 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(())
|
||||
}
|
||||
}
|
||||
);
|
||||
};
|
||||
}
|
120
net/epee-encoding/src/marker.rs
Normal file
120
net/epee-encoding/src/marker.rs
Normal 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,
|
||||
})
|
||||
}
|
||||
}
|
511
net/epee-encoding/src/value.rs
Normal file
511
net/epee-encoding/src/value.rs
Normal 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(())
|
||||
}
|
||||
}
|
91
net/epee-encoding/src/varint.rs
Normal file
91
net/epee-encoding/src/varint.rs
Normal 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);
|
||||
}
|
||||
}
|
35
net/epee-encoding/tests/alt_name.rs
Normal file
35
net/epee-encoding/tests/alt_name.rs
Normal 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);
|
||||
}
|
39
net/epee-encoding/tests/duplicate_key.rs
Normal file
39
net/epee-encoding/tests/duplicate_key.rs
Normal 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());
|
||||
}
|
74
net/epee-encoding/tests/epee_default.rs
Normal file
74
net/epee-encoding/tests/epee_default.rs
Normal 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)
|
||||
}
|
102
net/epee-encoding/tests/flattend.rs
Normal file
102
net/epee-encoding/tests/flattend.rs
Normal 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);
|
||||
}
|
31
net/epee-encoding/tests/options.rs
Normal file
31
net/epee-encoding/tests/options.rs
Normal 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);
|
||||
}
|
59
net/epee-encoding/tests/p2p.rs
Normal file
59
net/epee-encoding/tests/p2p.rs
Normal 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());
|
||||
}
|
83
net/epee-encoding/tests/rpc.rs
Normal file
83
net/epee-encoding/tests/rpc.rs
Normal 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());
|
||||
}
|
60
net/epee-encoding/tests/seq.rs
Normal file
60
net/epee-encoding/tests/seq.rs
Normal 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());
|
||||
}
|
741
net/epee-encoding/tests/stack_overflow.rs
Normal file
741
net/epee-encoding/tests/stack_overflow.rs
Normal 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())
|
||||
}
|
12
net/fixed-bytes/Cargo.toml
Normal file
12
net/fixed-bytes/Cargo.toml
Normal 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
126
net/fixed-bytes/src/lib.rs
Normal 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];
|
||||
}
|
||||
}
|
|
@ -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"]}
|
||||
|
||||
|
|
Loading…
Reference in a new issue