Crate vestaboard

source ·
Expand description

§vestaboard-rs

vestaboard-rs is a VBML (Vestaboard Markup Language) parser and api client for the Vestaboard. It supports the v2 read/write api, subscription api, and local api.

the full docs can be found at https://docs.rs/vestaboard

§features

  • VBML parser
  • read/write api
  • subscription api
  • local api
  • serialization and deserialization of Vestaboard messages
  • async/await
  • support for multiple Vestaboard sizes (if another size is released)

§installation

cargo add vestaboard -F full

§feature flags

  • full: enables all features
  • parser: enables the VBML parser (Vestaboard Markup Language) (default)
  • rw: enables the read/write api
  • subscription: enables the subscription api
  • local: enables the local api

§helpful type and structs

  • board::FLAGSHIP_ROWS and board::FLAGSHIP_COLS: the dimensions of the flagship Vestaboard
  • board::Board<ROWS, COLS>: a type equivalent to [[u8; COLS]; ROWS] which represents a Vestaboard state
  • BoardData<ROWS, COLS>: a struct that wraps a Board<ROWS, COLS> and has several helper methods
  • VBML: a struct that represents a VBML message and can be parsed into a BoardData<ROWS, COLS>
  • Vestaboard<Config>: the main struct that is used to interact with the Vestaboard api

§VBML usage

with ROWS and COLS specified:

let string = "{\"props\":{},\"style\":{},\"components\":[]}"; // any valid VBML string
let vbml: Vbml<6, 22> = string.parse().unwrap();

let board_data: Result<BoardData<6, 22>, VbmlError> = vbml.parse();

when ROWS and COLS are not specified, the default is board::FLAGSHIP_ROWS and board::FLAGSHIP_COLS:

let string = "{\"props\":{},\"style\":{},\"components\":[]}"; // any valid VBML string
let vbml: Vbml = string.parse().unwrap();

let board_data: Result<BoardData, VbmlError> = vbml.parse();

§api usage

use vestaboard::{Vestaboard, RWConfig, SubscriptionConfig, LocalConfig};

#[tokio::main]
async fn main() {
  let rw_config = RWConfig { read_write_key: "<YOUR_RW_API_KEY>" };
  let rw_api: Vestaboard<RWConfig> = Vestaboard::new_rw_api(rw_config);

  let subscription_config = SubscriptionConfig {
    api_key: "<YOUR_SUBSCRIPTION_API_KEY>",
    api_secret: "<YOUR_SUBSCRIPTION_API_SECRET>",
  };
  let subscription_api: Vestaboard<SubscriptionConfig> = Vestaboard::new_subscription_api(subscription_config);

  let local_config = LocalConfig {
    api_key: "<YOUR_LOCAL_API_KEY>",
    host: "<YOUR_VESTABOARD_IP_ADDRESS>",
  };
  let local_api: Vestaboard<LocalConfig> = Vestaboard::new_local_api(local_config);
}

(note that you must have the Vestaboard<Config> type specified due to this rust issue)

§read/write api

use vestaboard::{Vestaboard, RWConfig};

#[tokio::main]
async fn main() {
  let rw_config = RWConfig { read_write_key: "<YOUR_RW_API_KEY>" };
  let rw_api: Vestaboard<RWConfig> = Vestaboard::new_rw_api(rw_config);

  let message: Result<RWApiReadMessage, RWApiError> = rw_api.read().await;
  let write_res: Result<String, RWApiError> = rw_api.write(BoardData<ROWS, COLS>).await;
}

§subscription api

use vestaboard::{Vestaboard, SubscriptionConfig};

#[tokio::main]
async fn main() {
  let subscription_config = SubscriptionConfig {
    api_key: "<YOUR_SUBSCRIPTION_API_KEY>",
    api_secret: "<YOUR_SUBSCRIPTION_API_SECRET>",
  };
  let subscription_api: Vestaboard<SubscriptionConfig> = Vestaboard::new_subscription_api(subscription_config);

  let subscriptions: Result<SubscriptionsList, SubscriptionApiError> = subscription_api.get_subscriptions().await;
  let write_res: Result<SubscriptionMessageResponse, SubscriptionApiError> = subscription_api.write(BoardData<ROWS, COLS>).await;
}

§local api

use vestaboard::{Vestaboard, LocalConfig};

#[tokio::main]
async fn main() {
  // if you have not enabled the local api, you can use the following method to do so.
  // note that the local api can only be enabled once per board, so make sure to save
  // the resulting api key. to get the enablement token, visit https://www.vestaboard.com/local-api
  let local_api_enablement: Result<String, LocalApiError> = Vestaboard.get_local_api_key(
      Some("<YOUR_VESTABOARD_IP_ADDRESS>".parse().unwrap()),
      "<YOUR_LOCAL_API_ENABLEMENT_KEY>",
    ).await;

  let local_config = LocalConfig {
    api_key: "<YOUR_LOCAL_API_KEY>",
    ip_address: "<YOUR_VESTABOARD_IP_ADDRESS>".parse().unwrap(),
  };

  let local_api: Vestaboard<LocalConfig> = Vestaboard::new_local_api(local_config);

  let message: Result<BoardData<ROWS, COLS>, LocalApiError> = local_api.read().await;
  let write_res: Result<(), LocalApiError> = local_api.write(BoardData<ROWS, COLS>).await;
}

§benchmarks

this library is set up to be benchmarked against the official JavaScript VBML parsing library. benchmarks can be run using just with the following command:

just bench

on a Ryzen 9 7950X on Arch Linux with Node v18.20.0 and rustc 1.77.2, the benchmark results are as follows:

test namejs μs/itrs μs/itdifference% faster
Default Template21.23μs0.40μs-20.83μs5,338%
Half Height Center19.07μs0.40μs-18.68μs4,792%
Justify Left18.33μs0.39μs-17.94μs4,669%
Justify Right19.07μs0.39μs-18.68μs4,838%
Justify Center21.23μs0.39μs-20.84μs5,483%
Justify Justified20.11μs0.39μs-19.73μs5,192%
Align Center21.43μs0.39μs-21.05μs5,535%
Align Top18.98μs0.39μs-18.58μs4,812%
Align Bottom21.39μs0.39μs-21.00μs5,511%
Align Justified21.36μs0.39μs-20.97μs5,415%
Justify Justified Align Justified20.11μs0.38μs-19.73μs5,277%
Split Align Justify24.49μs0.42μs-24.08μs5,897%
Uneven Split23.85μs0.41μs-23.43μs5,770%
Uneven Split 221.64μs0.35μs-21.29μs6,244%
Rev Split Align Justify24.55μs0.42μs-24.13μs5,850%
Two Column21.61μs0.35μs-21.26μs6,153%
All Justified27.32μs0.42μs-26.90μs6,490%
Justified Right15.76μs0.24μs-15.51μs6,438%
Centered Right15.69μs0.24μs-15.45μs6,472%
2x2x2x2 Grid37.68μs0.76μs-36.91μs4,933%
2x2 Neighbors18.90μs0.37μs-18.53μs5,046%
Plain Text13.44μs0.24μs-13.20μs5,564%
Centered17.02μs0.24μs-16.78μs7,055%
Newline16.02μs0.26μs-15.76μs6,230%
Character Codes227.70μs17.94μs-209.77μs1,270%
Character Codes with Characters34.43μs1.52μs-32.91μs2,269%
Dynamic Props14.48μs0.65μs-13.82μs2,223%
Dynamic Props with Character Codes17.75μs1.13μs-16.62μs1,571%
Multiple Components49.01μs2.34μs-46.68μs2,099%
Raw Characters0.90μs0.04μs-0.86μs2,126%
Absolute Position Components24.33μs0.73μs-23.60μs3,311%
Complex Layout with Multiple Components70.41μs1.95μs-68.46μs3,619%
Complex Layout with Multiple Components 276.98μs2.12μs-74.86μs3,634%
Diff Height Components Newline30.00μs0.60μs-29.41μs5,028%
JS Spec: Absolute Layout18.19μs0.32μs-17.87μs5,714%
JS Spec: Absolute Layout 218.15μs0.32μs-17.83μs5,704%
JS Spec: Absolute and Raw Components12.08μs0.48μs-11.59μs2,496%

there is definitely further room for optimization, but the current performance is decent.

Re-exports§

Modules§

  • module for working with Vestaboard board representations.
  • locallocal
    local api (requires the local feature)
  • rwrw
    Vestaboard Read/Write api (requires the rw feature)
  • subscriptionsubscription
    Vestaboard subscription api (requires the subscription feature)
  • vbmlparser
    VBML Parser (requires parser feature)

Structs§

  • Vestaboardrw or subscription or local
    the main struct for interacting with the Vestaboard api.
    can interact with the r/w api, the subscription api, or the local api.