···11--- Add migration script here
22-create table if not exists records (
33- id text primary key,
44- parent text unique, -- null if this is the first one
55- host text not null,
66-77- timestamp integer not null,
88- tag text not null,
99- version text not null,
1010- data blob not null,
1111- cek blob not null
1212-);
1313-1414-create index host_idx on records (host);
1515-create index tag_idx on records (tag);
1616-create index host_tag_idx on records (host, tag);
···11--- Add migration script here
22-create table if not exists store (
33- id text primary key, -- globally unique ID
44-55- idx integer, -- incrementing integer ID unique per (host, tag)
66- host text not null, -- references the host row
77- tag text not null,
88-99- timestamp integer not null,
1010- version text not null,
1111- data blob not null,
1212- cek blob not null
1313-);
1414-1515-create unique index record_uniq ON store(host, tag, idx);
···11-use rmp::Marker;
22-use rmp::decode::bytes::{Bytes, BytesReadError};
33-use rmp::decode::{
44- self, DecodeStringError, NumValueReadError, RmpRead, RmpReadErr, ValueReadError,
55-};
66-use rmp::encode::{self, RmpWrite, RmpWriteErr, ValueWriteError};
77-88-/// An error encountered while trying to encode a message with [`rmp`].
99-///
1010-/// This is currently just a wrapper around [`ValueWriteError`] with a better error message.
1111-/// [`rmp`]'s error message does not indicate which variant the error is (`InvalidMarkerWrite` or
1212-/// `InvalidDataWrite`) and does not print anything about the inner I/O error of type `E`.
1313-#[derive(Debug, derive_more::Display, derive_more::From, thiserror::Error)]
1414-#[display("could not write MessagePack value: {_0:?}")]
1515-pub struct EncodeError<E: RmpWriteErr = std::io::Error>(ValueWriteError<E>);
1616-1717-/// An error encountered while trying to decode a message with [`rmp`].
1818-///
1919-/// This is a wrapper the various types of errors that can be returned by [`rmp`]'s decoding
2020-/// functions. Unlike those types, this type implements [`Display`] with an error message that
2121-/// indicates which variant the error is ([`rmp`]'s error types are enums; some unconditionally
2222-/// print a static string and others don't even implement [`Display`] for all `E`).
2323-///
2424-/// Conversion to [`eyre::Report`] is supported. This cannot be done by implementing
2525-/// [`std::error::Error`] because this type is not, in general, `'static`, so a manual
2626-/// implementation is provided.
2727-#[derive(Debug, derive_more::Display, derive_more::From)]
2828-#[display("could not decode MessagePack value: {_0:?}")]
2929-pub enum DecodeError<'a, E: RmpReadErr = BytesReadError> {
3030- DecodeString(DecodeStringError<'a, E>),
3131- NumValueRead(NumValueReadError<E>),
3232- ValueRead(ValueReadError<E>),
3333-}
3434-3535-impl<E: RmpReadErr> DecodeError<'_, E> {
3636- pub fn type_mismatch(&self) -> Option<Marker> {
3737- match self {
3838- Self::DecodeString(DecodeStringError::TypeMismatch(m)) => Some(*m),
3939- Self::NumValueRead(NumValueReadError::TypeMismatch(m)) => Some(*m),
4040- Self::ValueRead(ValueReadError::TypeMismatch(m)) => Some(*m),
4141- _ => None,
4242- }
4343- }
4444-}
4545-4646-impl<E: RmpReadErr> From<DecodeError<'_, E>> for eyre::Report {
4747- fn from(e: DecodeError<'_, E>) -> Self {
4848- eyre::eyre!("{e}")
4949- }
5050-}
5151-5252-/// Read an owned string from a [`Bytes`] object.
5353-///
5454-/// If you need an owned [`String`], this function is more convenient than using
5555-/// [`read_str_from_slice`] and converting the resulting [`str`], as you don't need to
5656-/// keep unwrapping and re-creating the [`Bytes`] object.
5757-///
5858-/// [`read_str_from_slice`]: decode::read_str_from_slice
5959-pub fn read_string<'a>(bytes: &mut Bytes<'a>) -> Result<String, DecodeError<'a>> {
6060- let slice = bytes.remaining_slice();
6161- let (string, rest) = match decode::read_str_from_slice(slice) {
6262- Ok(pair) => pair,
6363- Err(e) => {
6464- if let DecodeStringError::TypeMismatch(_) = e {
6565- // The decode functions in `rmp::decode` consume the marker byte when there's a
6666- // type mismatch; make sure we do that too, as `read_optional` depends on it.
6767- bytes
6868- .read_u8()
6969- .expect("TypeMismatch implies stream contains a marker byte");
7070- }
7171- return Err(e.into());
7272- }
7373- };
7474- *bytes = Bytes::new(rest);
7575- Ok(string.into())
7676-}
7777-7878-/// Read an optional value from the stream.
7979-///
8080-/// This function calls `read`, which should try to decode a value of type `T` from the stream. If
8181-/// that function returns an error indicating [`Marker::Null`] was encountered instead, this
8282-/// function returns [`None`]. All other errors are forwarded as-is.
8383-pub fn read_optional<'a, R, F, T, E>(
8484- input: &mut R,
8585- read: F,
8686-) -> Result<Option<T>, DecodeError<'a, R::Error>>
8787-where
8888- R: RmpRead,
8989- R::Error: Send + Sync,
9090- F: FnOnce(&mut R) -> Result<T, E>,
9191- E: Into<DecodeError<'a, R::Error>>,
9292-{
9393- let err = match read(input) {
9494- Ok(v) => return Ok(Some(v)),
9595- Err(e) => e.into(),
9696- };
9797-9898- if let Some(Marker::Null) = err.type_mismatch() {
9999- Ok(None)
100100- } else {
101101- Err(err)
102102- }
103103-}
104104-105105-/// Write an optional value to the stream.
106106-///
107107-/// If `value` is [`Some`], this function calls `write` with the value, which should encode a value
108108-/// of type `T` to the stream. Otherwise, this function writes [`Marker::Null`].
109109-pub fn write_optional<W, T, F>(
110110- output: &mut W,
111111- value: Option<T>,
112112- write: F,
113113-) -> Result<(), ValueWriteError<W::Error>>
114114-where
115115- W: RmpWrite,
116116- F: FnOnce(&mut W, T) -> Result<(), ValueWriteError<W::Error>>,
117117- W::Error: Send + Sync,
118118-{
119119- match value {
120120- Some(v) => write(output, v),
121121- None => encode::write_nil(output).map_err(ValueWriteError::InvalidMarkerWrite),
122122- }
123123-}
···11-use std::sync::Once;
22-33-static INIT: Once = Once::new();
44-55-/// Ensure the rustls crypto provider (ring) is installed.
66-///
77-/// Must be called before creating any reqwest clients. Safe to call
88-/// multiple times — only the first call installs the provider.
99-pub fn ensure_crypto_provider() {
1010- INIT.call_once(|| {
1111- rustls::crypto::ring::default_provider()
1212- .install_default()
1313- .expect("Failed to install rustls crypto provider");
1414- });
1515-}