A rust bencode encoding/decoding implementation backed by serde.

Related tags

Utilities bende
Overview

Bende

A rust bencode encoding/decoding implementation backed by serde.

About

This is one of a few bencode implementations available for rust. Though there are alternatives (see below), implementing bencode is both fun and a good learning experience. It also never hurts to have one more alternative.

Alternatives

There are more, but some are no longer maintained.

Usage

Add the library as a dependency to Cargo.toml

[dependencies]
bende = "0.5.1"
serde = { version = "1", features = ["derive"] }

Example

use serde::{Deserialize, Serialize};

#[derive(Debug, PartialEq, Serialize, Deserialize)]
struct Person {
    name: String,
    age: u8,
    is_employed: bool,
}

let jerry = Person {
    name: "Jerry Smith".to_string(),
    age: 50,
    is_employed: false,
};

let bytes = bende::encode(&jerry).unwrap();
assert_eq!(bende::decode::<Person>(&bytes).unwrap(), jerry);

Unsupported Types

The types that are currently not supported are:

  • f32
  • f64
  • char
  • enum

Floats will never be supported, but char and enum support will probably be added in the future.

Contributing

Contributions are what make the open source community such an amazing place to learn, inspire, and create. Any contributions you make are greatly appreciated.

If you have a suggestion that would make this better, please fork the repo and create a pull request. You can also simply open an issue with the tag "enhancement". Don't forget to give the project a star! Thanks again!

  1. Fork the Project
  2. Create your Feature Branch (git checkout -b feature/AmazingFeature)
  3. Commit your Changes (git commit -m 'Add some AmazingFeature')
  4. Push to the Branch (git push origin feature/AmazingFeature)
  5. Open a Pull Request

Notes

  • Both variants of Option<_> (Some and None) are supported by the decoder, but the encoder only supports Some.
  • Keys in a key-value object must be strings, otherwise an error is returned.
  • Map and struct entries are sorted lexicographically by their key before they are encoded.
  • If you run into trouble encoding/decoding raw bytes, eg: &[u8] or Vec<u8> then use this crate.
  • The codebase is relatively small (~2000 lines), easily digestible and filled with comments. If you're a first timer, you'll have a jolly time making your first contribution.
Comments
  • Proper unit and newtype_variant support

    Proper unit and newtype_variant support

    As of now, the library does not properly serialize or deserialize unit structs, unit variants, new type structs or new type variants:

    fn serialize_unit_struct(
        self,
        _: &'static str,
    ) -> Result<Self::Ok, Self::Error> {
        Ok(())
    }
    
    fn serialize_unit_variant(
        self,
        _: &'static str,
        _: u32,
        _: &'static str,
    ) -> Result<Self::Ok, Self::Error> {
        Ok(())
    }
    
    fn serialize_newtype_struct<T: ?Sized>(
        self,
        _: &'static str,
        _: &T,
    ) -> Result<Self::Ok, Self::Error>
    where
        T: serde::Serialize,
    {
        Ok(())
    }
    
    fn serialize_newtype_variant<T: ?Sized>(
        self,
        _: &'static str,
        _: u32,
        _: &'static str,
        _: &T,
    ) -> Result<Self::Ok, Self::Error>
    where
        T: serde::Serialize,
    {
        Ok(())
    }
    

    This is considered a bug and should be fixed accordingly.

    bug 
    opened by Rickz75 1
  • Docs/hide encoder types

    Docs/hide encoder types

    I've only just remembered that rust has a special #[doc(hidden)] attribute you can use to hide items from documentation. I've added it to both the SeqEncoder and MapEncoder types and removed the note saying that these types can't be constructed outside the crate.

    This does not change any behavior so I did not bump the package version.

    docs internal 
    opened by Rickz75 0
  • Feature: Enum Support

    Feature: Enum Support

    This PR introduces encoding and decoding support for enum types and their variants.

    Implementation

    Consider this enum:

    enum Enum {
        Unit,
        NewType(i32),
        Tuple(i32, i32),
        Struct { a: i32, b: i32 }
    }
    

    Each variant is encoded as such:

    • Enum::Unit => 4:Unit.
    • Enum::NewType(50) => d 7:NewType i50e e.
    • Enum::Tuple(25, 50) => d 5:Tuple l i25e i50e e e
    • Enum::Struct { a: 25, b: 50 } => d 6:Struct d 1:a i25e 1:b i50e e e

    Note that I only added whitespace to the examples above so they are more readable.

    I believe these changes are backwards-compatible, since no items were added or removed from the API. Because of this, I've bumped the package version to 0.5.4 and updated the readme accordingly.

    Upon a successful merge, this PR closes #2.

    enhancement 
    opened by Rickz75 0
  • Internal/test rework

    Internal/test rework

    This PR cleans up the unit tests for the following modules:

    • de.rs
    • en.rs
    • lib.rs

    I've added the macros test_decode, test_encode, and test_bende to each of these modules respectively, and used them to refactor repetitive testing patterns into a clearer and more readable code.

    Should this be merged into the main branch, then I believe it should resolve #3.

    Since there is no change in the public or private API, the version will remain the same as it is now.

    internal 
    opened by Rickz75 0
  • Feat/value methods

    Feat/value methods

    I've added a couple of useful methods to the Value type. The goal of these methods is to reduce boilerplate code for library users.

    I've also bumped the package version to 0.5.1 because I don't consider these additions as a breaking change.

    enhancement 
    opened by Halfnelson0 0
  • Feature: A Value type

    Feature: A Value type

    This PR introduces a new Value type - an enum that can represent any valid bencode data type.

    The en.rs and de.rs modules have been left untouched. The only change to lib.rs is that it exports the value type, and that it's docs now mention the new value type.

    This is a major change so I also bumped the package version to 0.5.0.

    enhancement 
    opened by Rickz75 0
  • Feat/sorted dict

    Feat/sorted dict

    As per #6, I've modified the MapEncoder type to sort key-value entries by key before encoding them.

    First off, there are two new error types:

    • KeyWithNoValue - When you try to encode a map entry's key without its respective value.
    • ValueWithNoKey - When you try to encode a map entry's value without its respective key.

    Then I modified the map encoder's fields, renaming the ambiguous en to encoder and adding two more fields:

    
    pub struct MapEncoder<'a, W> {
       encoder: &'a mut Encoder<W>, // Renamed.
       entries: BTreeMap<Vec<u8>, Vec<u8>>, // Stores and sorts entries by their key upon insertion.
       current_key: Option<Vec<u8>>, // Keeps track of the current entry's key.
    }
    
    

    In addition to modifying the map encoder, I've also changed how KeyEncoder behaves:

    Before

    
    fn serialize_str(self, v: &str) -> Result<Self::Ok, Self::Error> {
        self.en.serialize_str(v)
    }
    
    

    After

    
    fn serialize_str(self, v: &str) -> Result<Self::Ok, Self::Error> {
        self.en.write(v.as_bytes())
    }
    
    

    This is because we need to sort the key by their raw values before we encode them, otherwise the keys will be sorted by their length as well, which will result in this:

    d
        3:zzz i0e
        4:aaaa 3:foo
    e
    

    The key zzz comes first as it is seen as 3:zzz and aaaa will come second because it starts with 4.

    The other changes include:

    • Changing the ordering of the encoded byte literals in tests and examples.
    • I bumped the package version to 0.4.0.
    • I've updated the README to reflect that you need serde as a dependency to use any of the encoding/decode methods. And I also added a note to let users know that when they encode maps and structs, their entries will be sorted first.

    This is quite a change, but I doubt more changes of this magnitude will be added in the future.

    bug enhancement 
    opened by Rickz75 0
  • Dictionary entries should be sorted by key.

    Dictionary entries should be sorted by key.

    As per the bencode specification, dictionaries need to be sorted by their keys in lexicographical order.

    Currently, map and struct entries are encoded procedurally in the order they are given to the encoder. This of course is not how it should be done, and encoding them in an unspecified order should be and is considered incorrect behavior.

    I don't believe we should introduce sorting as a cargo feature, because the bencode spec requires you to sort dictionaries before encoding them - which means it is technically a bug.

    Altering the MapEncoder so that it sorts entries before encoding them will result in major changes in both the API's behavior and testing. But since map entries will always be sorted, future usage and testing of the library will be more deterministic, so it should then be considered more stable.

    This is quite a drastic change, but in the long run it will definitely pay off.

    bug enhancement 
    opened by Rickz75 0
  • Fix/string only keys

    Fix/string only keys

    An issue recently occurred to me. When encoding and decoding maps, the type of the keys is allowed to be any type. This of course is incorrect, because in bencode, dictionary keys must be of type string.

    This pull request resolves this incorrect behavior by ensuring keys are of type string before encoding and decoding them.

    bug enhancement 
    opened by Rickz75 0
  • Fix/units and newtypes

    Fix/units and newtypes

    I've added proper encoding and decoding support for unit structs (Foo) and new type structs (Foo(T)), alongside new tests.

    I've also bumped the package version to 0.2.1, because #2 considers that the previous implementation should be considered a bug.

    Unit variants and new type variants will only be properly implemented after we've added enum support.

    bug 
    opened by Rickz75 0
  • More tests

    More tests

    There are 20 tests at the moment, but it's not nearly enough.

    Here's a quick todo list:

    • [ ] All the different numerical types.
    • [ ] Vec<T>, &[T] and [T; N].
    • [ ] HashMap, HashSet, BTreeMap, BTreeSet
    • [ ] Units, tuples, tuple variants and tuple structs
    internal 
    opened by Rickz75 0
Owner
Du Toit
Du Toit
Derive macro for encoding/decoding instructions and operands as bytecode

bytecoding Derive macro for encoding and decoding instructions and operands as bytecode. Documentation License Licensed under either of Apache License

Niklas Sauter 15 Mar 20, 2022
serde-compatible redis library for Rust

Undis Undis is a serde-compatible redis library for Rust. WIP This project is currently under heavy development. Use it at your own risk. Todo Add #[d

Hyeonu Park 8 Jan 24, 2022
A Rust library that simplifies YAML serialization and deserialization using Serde.

Serde YML: Seamless YAML Serialization for Rust Serde YML is a Rust library that simplifies YAML serialization and deserialization using Serde. Effort

Sebastien Rousseau 4 Apr 4, 2024
serde support for http crate types Request, Response, Uri, StatusCode, HeaderMap

serde extensions for the http crate types Allows serializing and deserializing the following types from http: Response Request HeaderMap StatusCode Ur

Andrew Toth 3 Nov 1, 2023
A (de)serializer for RLP encoding in ETH

An ETH RLP (Recursive Length Prefix) (de)serializer written in Rust

M4tsuri 7 Jun 20, 2022
Rust implementation of the legacy Master Server Query Protocol

msq-rs Rust library implementation of the legacy Master Server Query Protocol. Documentation crates.io Repository Release Notes Usage Add this to your

mtcw 6 Nov 20, 2022
🦀 Rust-based implementation of a Snowflake Generator which communicates using gRPC

Clawflake Clawflake is a Rust application which implements Twitter Snowflakes and communicates using gRPC. Snowflake ID numbers are 63 bits integers s

n1c00o 5 Oct 31, 2022
Re-implementation of Panda Doodle in Rust targetting WASM, a mobile game originally written in C++

Description This is the source code of my game Panda Doodle, which can be played at https://pandadoodle.lucamoller.com/ (it's best playable on touch s

null 79 Dec 5, 2022
2D Predictive-Corrective Smoothed Particle Hydrodynamics (SPH) implementation in Rust with WASM + WebGL

pcisph-wasm 2D Predictive-Corrective Smoothed Particle Hydrodynamics (SPH) implementation in Rust with WASM + WebGL Reimplementation of my previous Ru

Lucas V. Schuermann 46 Dec 17, 2022
A Rust implementation of fractional indexing.

fractional_index This crate implements fractional indexing, a term coined by Figma in their blog post Realtime Editing of Ordered Sequences. Specifica

null 18 Dec 21, 2022
Pure rust implementation of jq

XQ JQ reimplemented purely in Rust. Caution This program is under development. You probably want to use the original implementation of jq, or pure Go

null 181 Jan 4, 2023
A pure Rust PLONK implementation using arkworks as a backend.

PLONK This is a pure Rust implementation of the PLONK zk proving system Usage use ark_plonk::prelude::*; use ark_ec::bls12::Bls12; use rand_core::OsRn

rust-zkp 201 Dec 31, 2022
A Bancho implementation made in Rust for the *cursed* stack.

cu.rs A Bancho implementation made in Rust for the cursed stack. THIS PROJECT IS REALLY UNFINISHED AND IN ITS EARLY STAGES A drag and drop replacement

RealistikOsu! 5 Feb 1, 2022
Golang like WaitGroup implementation for sync/async Rust.

wg Golang like WaitGroup implementation for sync/async Rust.

Al Liu 8 Dec 6, 2022
Hexdump implementation in Rust

Minimalistic hexdump implementation in Rust

null 1 Oct 25, 2021
Implementation of the WebUSB specification in Rust.

Implementation of the WebUSB specification in Rust.

Divy Srivastava 38 Dec 4, 2022
A Conway's Game of Life implementation in Rust & WASM

Rust Wasm Game of Life This repo contains an example implementation of Conway's Game of Life in Rust and WebAssembly. How to use You should have wasm-

Pierre-Yves Aillet 1 Nov 11, 2021
KERI implementation in RUST, current development lead by DIF

KERIOX Introduction Features Introduction KERIOX is an open source Rust implementation of the Key Event Receipt Infrastructure (KERI) , a system desig

WebOfTrust 3 Nov 11, 2022
A rust implementation of the reverse-engineered Glorious mouse protocol

gloryctl This project is an implementation of the vendor-specific HID protocol in use by Glorious mice used to configure parameters such as DPI profil

Samuel ÄŒavoj 6 Oct 17, 2022