mirror of
https://github.com/adoyle0/leptos-use.git
synced 2025-01-22 16:49:22 -05:00
codecs extracted into crate codee
This commit is contained in:
parent
c20d78c2ea
commit
e4ad9f11af
30 changed files with 70 additions and 725 deletions
2
.github/FUNDING.yml
vendored
2
.github/FUNDING.yml
vendored
|
@ -1,6 +1,6 @@
|
||||||
# These are supported funding model platforms
|
# These are supported funding model platforms
|
||||||
|
|
||||||
github: [Synphonyte]# Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
|
github: [Synphonyte] # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
|
||||||
patreon: # Replace with a single Patreon username
|
patreon: # Replace with a single Patreon username
|
||||||
open_collective: # Replace with a single Open Collective username
|
open_collective: # Replace with a single Open Collective username
|
||||||
ko_fi: # Replace with a single Ko-fi username
|
ko_fi: # Replace with a single Ko-fi username
|
||||||
|
|
8
.github/workflows/ci.yml
vendored
8
.github/workflows/ci.yml
vendored
|
@ -30,13 +30,13 @@ jobs:
|
||||||
- name: Check formatting
|
- name: Check formatting
|
||||||
run: cargo fmt --check
|
run: cargo fmt --check
|
||||||
- name: Clippy
|
- name: Clippy
|
||||||
run: cargo clippy --features prost,serde,docs,math --tests -- -D warnings
|
run: cargo clippy --features docs,math --tests -- -D warnings
|
||||||
- name: Run tests (general)
|
- name: Run tests (general)
|
||||||
run: cargo test --features math,docs,ssr,prost,json_serde,msgpack_serde,bincode_serde,base64
|
run: cargo test --features math,docs,ssr
|
||||||
- name: Run tests (axum)
|
- name: Run tests (axum)
|
||||||
run: cargo test --features math,docs,ssr,prost,json_serde,msgpack_serde,bincode_serde,base64,axum --doc use_cookie::use_cookie
|
run: cargo test --features math,docs,ssr,axum --doc use_cookie::use_cookie
|
||||||
- name: Run tests (actix)
|
- name: Run tests (actix)
|
||||||
run: cargo test --features math,docs,ssr,prost,json_serde,msgpack_serde,bincode_serde,base64,actix --doc use_cookie::use_cookie
|
run: cargo test --features math,docs,ssr,actix --doc use_cookie::use_cookie
|
||||||
|
|
||||||
#### mdbook
|
#### mdbook
|
||||||
- name: Install mdbook I
|
- name: Install mdbook I
|
||||||
|
|
8
.github/workflows/tests.yml
vendored
8
.github/workflows/tests.yml
vendored
|
@ -23,10 +23,10 @@ jobs:
|
||||||
- name: Check formatting
|
- name: Check formatting
|
||||||
run: cargo fmt --check
|
run: cargo fmt --check
|
||||||
- name: Clippy
|
- name: Clippy
|
||||||
run: cargo clippy --features prost,serde,docs,math --tests -- -D warnings
|
run: cargo clippy --features docs,math --tests -- -D warnings
|
||||||
- name: Run tests (general)
|
- name: Run tests (general)
|
||||||
run: cargo test --features math,docs,ssr,prost,json_serde,msgpack_serde,bincode_serde,base64
|
run: cargo test --features math,docs,ssr
|
||||||
- name: Run tests (axum)
|
- name: Run tests (axum)
|
||||||
run: cargo test --features math,docs,ssr,prost,json_serde,msgpack_serde,bincode_serde,base64,axum --doc use_cookie::use_cookie
|
run: cargo test --features math,docs,ssr,axum --doc use_cookie::use_cookie
|
||||||
- name: Run tests (actix)
|
- name: Run tests (actix)
|
||||||
run: cargo test --features math,docs,ssr,prost,json_serde,msgpack_serde,bincode_serde,base64,actix --doc use_cookie::use_cookie
|
run: cargo test --features math,docs,ssr,actix --doc use_cookie::use_cookie
|
||||||
|
|
17
Cargo.toml
17
Cargo.toml
|
@ -15,9 +15,8 @@ homepage = "https://leptos-use.rs"
|
||||||
[dependencies]
|
[dependencies]
|
||||||
actix-web = { version = "4", optional = true, default-features = false }
|
actix-web = { version = "4", optional = true, default-features = false }
|
||||||
async-trait = "0.1"
|
async-trait = "0.1"
|
||||||
base64 = { version = "0.21", optional = true }
|
|
||||||
cfg-if = "1"
|
cfg-if = "1"
|
||||||
bincode = { version = "1", optional = true }
|
codee = "0.1"
|
||||||
cookie = { version = "0.18", features = ["percent-encode"] }
|
cookie = { version = "0.18", features = ["percent-encode"] }
|
||||||
default-struct-builder = "0.5"
|
default-struct-builder = "0.5"
|
||||||
futures-util = "0.3"
|
futures-util = "0.3"
|
||||||
|
@ -33,10 +32,6 @@ leptos_actix = { version = "0.6", optional = true }
|
||||||
leptos-spin = { version = "0.1", optional = true }
|
leptos-spin = { version = "0.1", optional = true }
|
||||||
num = { version = "0.4", optional = true }
|
num = { version = "0.4", optional = true }
|
||||||
paste = "1"
|
paste = "1"
|
||||||
prost = { version = "0.12", optional = true }
|
|
||||||
rmp-serde = { version = "1.1", optional = true }
|
|
||||||
serde = { version = "1", optional = true }
|
|
||||||
serde_json = { version = "1", optional = true }
|
|
||||||
thiserror = "1"
|
thiserror = "1"
|
||||||
wasm-bindgen = "0.2.92"
|
wasm-bindgen = "0.2.92"
|
||||||
wasm-bindgen-futures = "0.4"
|
wasm-bindgen-futures = "0.4"
|
||||||
|
@ -136,19 +131,19 @@ features = [
|
||||||
getrandom = { version = "0.2", features = ["js"] }
|
getrandom = { version = "0.2", features = ["js"] }
|
||||||
leptos_meta = "0.6"
|
leptos_meta = "0.6"
|
||||||
rand = "0.8"
|
rand = "0.8"
|
||||||
|
codee = { version = "0.1", features = ["json_serde", "msgpack_serde", "base64", "prost"] }
|
||||||
|
serde = { version = "1", features = ["derive"] }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
actix = ["dep:actix-web", "dep:leptos_actix", "dep:http0_2"]
|
actix = ["dep:actix-web", "dep:leptos_actix", "dep:http0_2"]
|
||||||
axum = ["dep:leptos_axum", "dep:http1"]
|
axum = ["dep:leptos_axum", "dep:http1"]
|
||||||
docs = []
|
docs = []
|
||||||
math = ["num"]
|
math = ["num"]
|
||||||
prost = ["dep:prost"]
|
|
||||||
json_serde = ["dep:serde_json", "dep:serde"]
|
|
||||||
spin = ["dep:leptos-spin", "dep:http1"]
|
spin = ["dep:leptos-spin", "dep:http1"]
|
||||||
ssr = []
|
ssr = []
|
||||||
msgpack_serde = ["dep:rmp-serde", "dep:serde"]
|
|
||||||
bincode_serde = ["dep:bincode", "dep:serde"]
|
|
||||||
wasm_ssr = []
|
wasm_ssr = []
|
||||||
|
|
||||||
[package.metadata.docs.rs]
|
[package.metadata.docs.rs]
|
||||||
features = ["math", "docs", "ssr", "prost", "json_serde", "msgpack_serde", "bincode_serde"]
|
features = ["math", "docs", "ssr"]
|
||||||
|
rustdoc-args = ["--cfg=web_sys_unstable_apis"]
|
||||||
|
rustc-args = ["--cfg=web_sys_unstable_apis"]
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
[Introduction](introduction.md)
|
[Introduction](introduction.md)
|
||||||
[Get Started](get_started.md)
|
[Get Started](get_started.md)
|
||||||
|
[Options](options.md)
|
||||||
[Element Parameters](element_parameters.md)
|
[Element Parameters](element_parameters.md)
|
||||||
[Server-Side Rendering](server_side_rendering.md)
|
[Server-Side Rendering](server_side_rendering.md)
|
||||||
[Encoding and Decoding Data](codecs.md)
|
[Encoding and Decoding Data](codecs.md)
|
||||||
|
|
22
docs/book/src/options.md
Normal file
22
docs/book/src/options.md
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
# Options
|
||||||
|
|
||||||
|
Most functions in Leptos-Use come with a version `..._with_options`. For example `use_css_var` has a
|
||||||
|
version `use_css_var_with_options`. As the name suggests, you can provide additional options to those versions of the
|
||||||
|
functions.
|
||||||
|
|
||||||
|
These options are defined as structs with the corresponding PascalCase name. For our example `use_css_var_with_options`
|
||||||
|
the name of the struct is `UseCssVarOptions`. Every option struct implements `Default` and the builder pattern to
|
||||||
|
make it easy to change only the values needed. This can look like the following example.
|
||||||
|
|
||||||
|
```rust
|
||||||
|
let (color, set_color) = use_css_var_with_options(
|
||||||
|
"--color",
|
||||||
|
UseCssVarOptions::default()
|
||||||
|
.target(el)
|
||||||
|
.initial_value("#eee"),
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
Here only the values `target` and `initial_value` are changed and everything else is left to default.
|
||||||
|
|
||||||
|
TODO : automatic conversion like Fn and Option
|
|
@ -4,11 +4,12 @@ version = "0.1.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
codee = { path = "../../../codee", features = ["json_serde"] }
|
||||||
leptos = { version = "0.6", features = ["nightly", "csr"] }
|
leptos = { version = "0.6", features = ["nightly", "csr"] }
|
||||||
console_error_panic_hook = "0.1"
|
console_error_panic_hook = "0.1"
|
||||||
console_log = "1"
|
console_log = "1"
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
leptos-use = { path = "../..", features = ["docs", "json_serde"] }
|
leptos-use = { path = "../..", features = ["docs"] }
|
||||||
web-sys = "0.3"
|
web-sys = "0.3"
|
||||||
serde = "1.0.163"
|
serde = "1.0.163"
|
||||||
|
|
||||||
|
|
|
@ -5,10 +5,11 @@ edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
leptos = { version = "0.6", features = ["nightly", "csr"] }
|
leptos = { version = "0.6", features = ["nightly", "csr"] }
|
||||||
|
codee = { path = "../../../codee", features = ["msgpack_serde"] }
|
||||||
console_error_panic_hook = "0.1"
|
console_error_panic_hook = "0.1"
|
||||||
console_log = "1"
|
console_log = "1"
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
leptos-use = { path = "../..", features = ["docs", "msgpack_serde"] }
|
leptos-use = { path = "../..", features = ["docs"] }
|
||||||
serde = { version = "1", features = ["derive"] }
|
serde = { version = "1", features = ["derive"] }
|
||||||
web-sys = "0.3"
|
web-sys = "0.3"
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ use leptos_use::{
|
||||||
};
|
};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use leptos_use::utils::{FromToStringCodec, MsgpackSerdeCodec};
|
use codee::{binary::MsgpackSerdeCodec, string::FromToStringCodec};
|
||||||
use web_sys::{CloseEvent, Event};
|
use web_sys::{CloseEvent, Event};
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use super::{use_storage_with_options, StorageType, UseStorageOptions};
|
use super::{use_storage_with_options, StorageType, UseStorageOptions};
|
||||||
use crate::utils::{Decoder, Encoder};
|
use codee::{Decoder, Encoder};
|
||||||
use leptos::signal_prelude::*;
|
use leptos::signal_prelude::*;
|
||||||
|
|
||||||
/// Reactive [LocalStorage](https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage).
|
/// Reactive [LocalStorage](https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage).
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use super::{use_storage_with_options, StorageType, UseStorageOptions};
|
use super::{use_storage_with_options, StorageType, UseStorageOptions};
|
||||||
use crate::utils::{Decoder, Encoder};
|
use codee::{Decoder, Encoder};
|
||||||
use leptos::signal_prelude::*;
|
use leptos::signal_prelude::*;
|
||||||
|
|
||||||
/// Reactive [SessionStorage](https://developer.mozilla.org/en-US/docs/Web/API/Window/sessionStorage).
|
/// Reactive [SessionStorage](https://developer.mozilla.org/en-US/docs/Web/API/Window/sessionStorage).
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
use crate::utils::{CodecError, Decoder, Encoder};
|
|
||||||
use crate::{
|
use crate::{
|
||||||
core::{MaybeRwSignal, StorageType},
|
core::{MaybeRwSignal, StorageType},
|
||||||
utils::FilterOptions,
|
utils::FilterOptions,
|
||||||
};
|
};
|
||||||
|
use codee::{CodecError, Decoder, Encoder};
|
||||||
use default_struct_builder::DefaultBuilder;
|
use default_struct_builder::DefaultBuilder;
|
||||||
use leptos::*;
|
use leptos::*;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
@ -39,7 +39,8 @@ const INTERNAL_STORAGE_EVENT: &str = "leptos-use-storage";
|
||||||
/// # use leptos::*;
|
/// # use leptos::*;
|
||||||
/// # use leptos_use::storage::{StorageType, use_local_storage, use_session_storage, use_storage};
|
/// # use leptos_use::storage::{StorageType, use_local_storage, use_session_storage, use_storage};
|
||||||
/// # use serde::{Deserialize, Serialize};
|
/// # use serde::{Deserialize, Serialize};
|
||||||
/// # use leptos_use::utils::{FromToStringCodec, JsonSerdeCodec, ProstCodec, Base64};
|
/// # use codee::string::{FromToStringCodec, JsonSerdeCodec, Base64};
|
||||||
|
/// # use codee::binary::ProstCodec;
|
||||||
/// #
|
/// #
|
||||||
/// # #[component]
|
/// # #[component]
|
||||||
/// # pub fn Demo() -> impl IntoView {
|
/// # pub fn Demo() -> impl IntoView {
|
||||||
|
@ -94,7 +95,7 @@ const INTERNAL_STORAGE_EVENT: &str = "leptos-use-storage";
|
||||||
/// ```
|
/// ```
|
||||||
/// # use leptos::*;
|
/// # use leptos::*;
|
||||||
/// # use leptos_use::storage::use_session_storage;
|
/// # use leptos_use::storage::use_session_storage;
|
||||||
/// # use leptos_use::utils::FromToStringCodec;
|
/// # use codee::string::FromToStringCodec;
|
||||||
/// #
|
/// #
|
||||||
/// # #[component]
|
/// # #[component]
|
||||||
/// # pub fn Example() -> impl IntoView {
|
/// # pub fn Example() -> impl IntoView {
|
||||||
|
@ -127,7 +128,7 @@ const INTERNAL_STORAGE_EVENT: &str = "leptos-use-storage";
|
||||||
/// ```
|
/// ```
|
||||||
/// # use leptos::*;
|
/// # use leptos::*;
|
||||||
/// # use leptos_use::storage::{use_local_storage_with_options, UseStorageOptions};
|
/// # use leptos_use::storage::{use_local_storage_with_options, UseStorageOptions};
|
||||||
/// # use leptos_use::utils::FromToStringCodec;
|
/// # use codee::string::FromToStringCodec;
|
||||||
/// #
|
/// #
|
||||||
/// # #[component]
|
/// # #[component]
|
||||||
/// # pub fn Example() -> impl IntoView {
|
/// # pub fn Example() -> impl IntoView {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use crate::utils::{CodecError, Decoder, Encoder};
|
|
||||||
use crate::{
|
use crate::{
|
||||||
js, use_event_listener, use_event_listener_with_options, use_supported, UseEventListenerOptions,
|
js, use_event_listener, use_event_listener_with_options, use_supported, UseEventListenerOptions,
|
||||||
};
|
};
|
||||||
|
use codee::{CodecError, Decoder, Encoder};
|
||||||
use leptos::*;
|
use leptos::*;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
use wasm_bindgen::JsValue;
|
use wasm_bindgen::JsValue;
|
||||||
|
@ -23,7 +23,7 @@ use wasm_bindgen::JsValue;
|
||||||
/// ```
|
/// ```
|
||||||
/// # use leptos::*;
|
/// # use leptos::*;
|
||||||
/// # use leptos_use::{use_broadcast_channel, UseBroadcastChannelReturn};
|
/// # use leptos_use::{use_broadcast_channel, UseBroadcastChannelReturn};
|
||||||
/// # use leptos_use::utils::FromToStringCodec;
|
/// # use codee::string::FromToStringCodec;
|
||||||
/// #
|
/// #
|
||||||
/// # #[component]
|
/// # #[component]
|
||||||
/// # fn Demo() -> impl IntoView {
|
/// # fn Demo() -> impl IntoView {
|
||||||
|
@ -54,7 +54,7 @@ use wasm_bindgen::JsValue;
|
||||||
/// # use leptos::*;
|
/// # use leptos::*;
|
||||||
/// # use serde::{Deserialize, Serialize};
|
/// # use serde::{Deserialize, Serialize};
|
||||||
/// # use leptos_use::use_broadcast_channel;
|
/// # use leptos_use::use_broadcast_channel;
|
||||||
/// # use leptos_use::utils::JsonSerdeCodec;
|
/// # use codee::string::JsonSerdeCodec;
|
||||||
/// #
|
/// #
|
||||||
/// // Data sent in JSON must implement Serialize, Deserialize:
|
/// // Data sent in JSON must implement Serialize, Deserialize:
|
||||||
/// #[derive(Serialize, Deserialize, Clone, PartialEq)]
|
/// #[derive(Serialize, Deserialize, Clone, PartialEq)]
|
||||||
|
|
|
@ -2,8 +2,8 @@ use crate::core::url;
|
||||||
use crate::core::StorageType;
|
use crate::core::StorageType;
|
||||||
use crate::core::{ElementMaybeSignal, MaybeRwSignal};
|
use crate::core::{ElementMaybeSignal, MaybeRwSignal};
|
||||||
use crate::storage::{use_storage_with_options, UseStorageOptions};
|
use crate::storage::{use_storage_with_options, UseStorageOptions};
|
||||||
use crate::utils::FromToStringCodec;
|
|
||||||
use crate::{sync_signal_with_options, use_cookie, use_preferred_dark, SyncSignalOptions};
|
use crate::{sync_signal_with_options, use_cookie, use_preferred_dark, SyncSignalOptions};
|
||||||
|
use codee::string::FromToStringCodec;
|
||||||
use default_struct_builder::DefaultBuilder;
|
use default_struct_builder::DefaultBuilder;
|
||||||
use leptos::*;
|
use leptos::*;
|
||||||
use std::fmt::{Display, Formatter};
|
use std::fmt::{Display, Formatter};
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#![allow(clippy::too_many_arguments)]
|
#![allow(clippy::too_many_arguments)]
|
||||||
|
|
||||||
use crate::core::now;
|
use crate::core::now;
|
||||||
use crate::utils::{CodecError, Decoder, Encoder};
|
use codee::{CodecError, Decoder, Encoder};
|
||||||
use cookie::time::{Duration, OffsetDateTime};
|
use cookie::time::{Duration, OffsetDateTime};
|
||||||
pub use cookie::SameSite;
|
pub use cookie::SameSite;
|
||||||
use cookie::{Cookie, CookieJar};
|
use cookie::{Cookie, CookieJar};
|
||||||
|
@ -30,7 +30,7 @@ use std::rc::Rc;
|
||||||
/// ```
|
/// ```
|
||||||
/// # use leptos::*;
|
/// # use leptos::*;
|
||||||
/// # use leptos_use::use_cookie;
|
/// # use leptos_use::use_cookie;
|
||||||
/// # use leptos_use::utils::FromToStringCodec;
|
/// # use codee::string::FromToStringCodec;
|
||||||
/// # use rand::prelude::*;
|
/// # use rand::prelude::*;
|
||||||
///
|
///
|
||||||
/// #
|
/// #
|
||||||
|
@ -70,7 +70,7 @@ use std::rc::Rc;
|
||||||
/// # use cookie::SameSite;
|
/// # use cookie::SameSite;
|
||||||
/// # use leptos::*;
|
/// # use leptos::*;
|
||||||
/// # use leptos_use::{use_cookie_with_options, UseCookieOptions};
|
/// # use leptos_use::{use_cookie_with_options, UseCookieOptions};
|
||||||
/// # use leptos_use::utils::FromToStringCodec;
|
/// # use codee::string::FromToStringCodec;
|
||||||
/// #
|
/// #
|
||||||
/// # #[component]
|
/// # #[component]
|
||||||
/// # fn Demo() -> impl IntoView {
|
/// # fn Demo() -> impl IntoView {
|
||||||
|
@ -105,7 +105,7 @@ use std::rc::Rc;
|
||||||
/// # use leptos::*;
|
/// # use leptos::*;
|
||||||
/// # use serde::{Deserialize, Serialize};
|
/// # use serde::{Deserialize, Serialize};
|
||||||
/// # use leptos_use::{use_cookie_with_options, UseCookieOptions};
|
/// # use leptos_use::{use_cookie_with_options, UseCookieOptions};
|
||||||
/// # use leptos_use::utils::JsonSerdeCodec;
|
/// # use codee::string::JsonSerdeCodec;
|
||||||
/// #
|
/// #
|
||||||
/// # #[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
|
/// # #[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
|
||||||
/// # pub struct Auth {
|
/// # pub struct Auth {
|
||||||
|
@ -215,10 +215,10 @@ where
|
||||||
|
|
||||||
#[cfg(not(feature = "ssr"))]
|
#[cfg(not(feature = "ssr"))]
|
||||||
{
|
{
|
||||||
use crate::utils::{FromToStringCodec, OptionCodec};
|
|
||||||
use crate::{
|
use crate::{
|
||||||
use_broadcast_channel, watch_pausable, UseBroadcastChannelReturn, WatchPausableReturn,
|
use_broadcast_channel, watch_pausable, UseBroadcastChannelReturn, WatchPausableReturn,
|
||||||
};
|
};
|
||||||
|
use codee::string::{FromToStringCodec, OptionCodec};
|
||||||
|
|
||||||
let UseBroadcastChannelReturn { message, post, .. } =
|
let UseBroadcastChannelReturn { message, post, .. } =
|
||||||
use_broadcast_channel::<Option<String>, OptionCodec<FromToStringCodec>>(&format!(
|
use_broadcast_channel::<Option<String>, OptionCodec<FromToStringCodec>>(&format!(
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::core::ConnectionReadyState;
|
use crate::core::ConnectionReadyState;
|
||||||
use crate::utils::Decoder;
|
|
||||||
use crate::{js, use_event_listener, ReconnectLimit};
|
use crate::{js, use_event_listener, ReconnectLimit};
|
||||||
|
use codee::Decoder;
|
||||||
use default_struct_builder::DefaultBuilder;
|
use default_struct_builder::DefaultBuilder;
|
||||||
use leptos::*;
|
use leptos::*;
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
|
@ -27,7 +27,8 @@ use thiserror::Error;
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// # use leptos::*;
|
/// # use leptos::*;
|
||||||
/// # use leptos_use::{use_event_source, UseEventSourceReturn, utils::JsonSerdeCodec};
|
/// # use leptos_use::{use_event_source, UseEventSourceReturn};
|
||||||
|
/// # use codee::string::JsonSerdeCodec;
|
||||||
/// # use serde::{Deserialize, Serialize};
|
/// # use serde::{Deserialize, Serialize};
|
||||||
/// #
|
/// #
|
||||||
/// #[derive(Serialize, Deserialize, Clone, PartialEq)]
|
/// #[derive(Serialize, Deserialize, Clone, PartialEq)]
|
||||||
|
@ -56,7 +57,8 @@ use thiserror::Error;
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// # use leptos::*;
|
/// # use leptos::*;
|
||||||
/// # use leptos_use::{use_event_source_with_options, UseEventSourceReturn, UseEventSourceOptions, utils::FromToStringCodec};
|
/// # use leptos_use::{use_event_source_with_options, UseEventSourceReturn, UseEventSourceOptions};
|
||||||
|
/// # use codee::string::FromToStringCodec;
|
||||||
/// #
|
/// #
|
||||||
/// # #[component]
|
/// # #[component]
|
||||||
/// # fn Demo() -> impl IntoView {
|
/// # fn Demo() -> impl IntoView {
|
||||||
|
@ -87,7 +89,8 @@ use thiserror::Error;
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// # use leptos::*;
|
/// # use leptos::*;
|
||||||
/// # use leptos_use::{use_event_source_with_options, UseEventSourceReturn, UseEventSourceOptions, utils::FromToStringCodec, ReconnectLimit};
|
/// # use leptos_use::{use_event_source_with_options, UseEventSourceReturn, UseEventSourceOptions, ReconnectLimit};
|
||||||
|
/// # use codee::string::FromToStringCodec;
|
||||||
/// #
|
/// #
|
||||||
/// # #[component]
|
/// # #[component]
|
||||||
/// # fn Demo() -> impl IntoView {
|
/// # fn Demo() -> impl IntoView {
|
||||||
|
|
|
@ -8,7 +8,7 @@ use std::time::Duration;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
use crate::core::ConnectionReadyState;
|
use crate::core::ConnectionReadyState;
|
||||||
use crate::utils::{
|
use codee::{
|
||||||
CodecError, Decoder, Encoder, HybridCoderError, HybridDecoder, HybridEncoder, IsBinary,
|
CodecError, Decoder, Encoder, HybridCoderError, HybridDecoder, HybridEncoder, IsBinary,
|
||||||
};
|
};
|
||||||
use default_struct_builder::DefaultBuilder;
|
use default_struct_builder::DefaultBuilder;
|
||||||
|
@ -31,7 +31,7 @@ use web_sys::{BinaryType, CloseEvent, Event, MessageEvent, WebSocket};
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// # use leptos::*;
|
/// # use leptos::*;
|
||||||
/// # use leptos_use::utils::FromToStringCodec;
|
/// # use codee::string::FromToStringCodec;
|
||||||
/// # use leptos_use::{use_websocket, UseWebSocketReturn};
|
/// # use leptos_use::{use_websocket, UseWebSocketReturn};
|
||||||
/// # use leptos_use::core::ConnectionReadyState;
|
/// # use leptos_use::core::ConnectionReadyState;
|
||||||
/// #
|
/// #
|
||||||
|
@ -81,7 +81,7 @@ use web_sys::{BinaryType, CloseEvent, Event, MessageEvent, WebSocket};
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// # use leptos::*;
|
/// # use leptos::*;
|
||||||
/// # use leptos_use::utils::MsgpackSerdeCodec;
|
/// # use codee::binary::MsgpackSerdeCodec;
|
||||||
/// # use leptos_use::{use_websocket, UseWebSocketReturn};
|
/// # use leptos_use::{use_websocket, UseWebSocketReturn};
|
||||||
/// # use serde::{Deserialize, Serialize};
|
/// # use serde::{Deserialize, Serialize};
|
||||||
/// #
|
/// #
|
||||||
|
@ -164,7 +164,7 @@ use web_sys::{BinaryType, CloseEvent, Event, MessageEvent, WebSocket};
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// # use leptos::*;
|
/// # use leptos::*;
|
||||||
/// # use leptos_use::utils::FromToStringCodec;
|
/// # use codee::string::FromToStringCodec;
|
||||||
/// # use leptos_use::{use_websocket, UseWebSocketReturn};
|
/// # use leptos_use::{use_websocket, UseWebSocketReturn};
|
||||||
/// # use std::rc::Rc;
|
/// # use std::rc::Rc;
|
||||||
/// # #[derive(Clone)]
|
/// # #[derive(Clone)]
|
||||||
|
|
|
@ -1,45 +0,0 @@
|
||||||
use crate::utils::{Decoder, Encoder};
|
|
||||||
|
|
||||||
/// A codec that relies on `bincode` adn `serde` to encode data in the bincode format.
|
|
||||||
///
|
|
||||||
/// This is only available with the **`bincode` feature** enabled.
|
|
||||||
pub struct BincodeSerdeCodec;
|
|
||||||
|
|
||||||
impl<T: serde::Serialize> Encoder<T> for BincodeSerdeCodec {
|
|
||||||
type Error = bincode::Error;
|
|
||||||
type Encoded = Vec<u8>;
|
|
||||||
|
|
||||||
fn encode(val: &T) -> Result<Self::Encoded, Self::Error> {
|
|
||||||
bincode::serialize(val)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: serde::de::DeserializeOwned> Decoder<T> for BincodeSerdeCodec {
|
|
||||||
type Error = bincode::Error;
|
|
||||||
type Encoded = [u8];
|
|
||||||
|
|
||||||
fn decode(val: &Self::Encoded) -> Result<T, Self::Error> {
|
|
||||||
bincode::deserialize(val)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_bincode_codec() {
|
|
||||||
#[derive(Clone, Debug, PartialEq, serde::Serialize, serde::Deserialize)]
|
|
||||||
struct Test {
|
|
||||||
s: String,
|
|
||||||
i: i32,
|
|
||||||
}
|
|
||||||
let t = Test {
|
|
||||||
s: String::from("party time 🎉"),
|
|
||||||
i: 42,
|
|
||||||
};
|
|
||||||
let enc = BincodeSerdeCodec::encode(&t).unwrap();
|
|
||||||
let dec: Test = BincodeSerdeCodec::decode(&enc).unwrap();
|
|
||||||
assert_eq!(dec, t);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,112 +0,0 @@
|
||||||
use crate::utils::{Decoder, Encoder};
|
|
||||||
use thiserror::Error;
|
|
||||||
|
|
||||||
/// A binary codec that uses rust own binary encoding functions to encode and decode data.
|
|
||||||
/// This can be used if you want to encode only primitives and don't want to rely on third party
|
|
||||||
/// crates like `bincode` or `rmp-serde`. If you have more complex data check out
|
|
||||||
/// [`BincodeSerdeCodec`] or [`MsgpackSerdeCodec`].
|
|
||||||
pub struct FromToBytesCodec;
|
|
||||||
|
|
||||||
#[derive(Error, Debug)]
|
|
||||||
pub enum FromToBytesCodecError {
|
|
||||||
#[error("failed to convert byte slice to byte array")]
|
|
||||||
InvalidByteSlice(#[from] std::array::TryFromSliceError),
|
|
||||||
|
|
||||||
#[error("failed to convert byte array to string")]
|
|
||||||
InvalidString(#[from] std::string::FromUtf8Error),
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! impl_bin_codec_for_number {
|
|
||||||
($num:ty) => {
|
|
||||||
impl Encoder<$num> for FromToBytesCodec {
|
|
||||||
type Error = ();
|
|
||||||
type Encoded = Vec<u8>;
|
|
||||||
|
|
||||||
fn encode(val: &$num) -> Result<Self::Encoded, Self::Error> {
|
|
||||||
Ok(val.to_be_bytes().to_vec())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Decoder<$num> for FromToBytesCodec {
|
|
||||||
type Error = FromToBytesCodecError;
|
|
||||||
type Encoded = [u8];
|
|
||||||
|
|
||||||
fn decode(val: &Self::Encoded) -> Result<$num, Self::Error> {
|
|
||||||
Ok(<$num>::from_be_bytes(val.try_into()?))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
impl_bin_codec_for_number!(i8);
|
|
||||||
impl_bin_codec_for_number!(u8);
|
|
||||||
|
|
||||||
impl_bin_codec_for_number!(i16);
|
|
||||||
impl_bin_codec_for_number!(u16);
|
|
||||||
|
|
||||||
impl_bin_codec_for_number!(i32);
|
|
||||||
impl_bin_codec_for_number!(u32);
|
|
||||||
|
|
||||||
impl_bin_codec_for_number!(i64);
|
|
||||||
impl_bin_codec_for_number!(u64);
|
|
||||||
|
|
||||||
impl_bin_codec_for_number!(i128);
|
|
||||||
impl_bin_codec_for_number!(u128);
|
|
||||||
|
|
||||||
impl_bin_codec_for_number!(isize);
|
|
||||||
impl_bin_codec_for_number!(usize);
|
|
||||||
|
|
||||||
impl_bin_codec_for_number!(f32);
|
|
||||||
impl_bin_codec_for_number!(f64);
|
|
||||||
|
|
||||||
impl Encoder<bool> for FromToBytesCodec {
|
|
||||||
type Error = ();
|
|
||||||
type Encoded = Vec<u8>;
|
|
||||||
|
|
||||||
fn encode(val: &bool) -> Result<Self::Encoded, Self::Error> {
|
|
||||||
let num: u8 = if *val { 1 } else { 0 };
|
|
||||||
Self::encode(&num)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Decoder<bool> for FromToBytesCodec {
|
|
||||||
type Error = FromToBytesCodecError;
|
|
||||||
type Encoded = [u8];
|
|
||||||
|
|
||||||
fn decode(val: &Self::Encoded) -> Result<bool, Self::Error> {
|
|
||||||
let num: u8 = Self::decode(val)?;
|
|
||||||
Ok(num != 0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Encoder<String> for FromToBytesCodec {
|
|
||||||
type Error = ();
|
|
||||||
type Encoded = Vec<u8>;
|
|
||||||
|
|
||||||
fn encode(val: &String) -> Result<Self::Encoded, Self::Error> {
|
|
||||||
Ok(val.as_bytes().to_vec())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Decoder<String> for FromToBytesCodec {
|
|
||||||
type Error = FromToBytesCodecError;
|
|
||||||
type Encoded = [u8];
|
|
||||||
|
|
||||||
fn decode(val: &Self::Encoded) -> Result<String, Self::Error> {
|
|
||||||
Ok(String::from_utf8(val.to_vec())?)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_fromtobytes_codec() {
|
|
||||||
let t = 50;
|
|
||||||
|
|
||||||
let enc: Vec<u8> = FromToBytesCodec::encode(&t).unwrap();
|
|
||||||
let dec: i32 = FromToBytesCodec::decode(enc.as_slice()).unwrap();
|
|
||||||
assert_eq!(dec, t);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,16 +0,0 @@
|
||||||
#[cfg(feature = "bincode_serde")]
|
|
||||||
mod bincode_serde;
|
|
||||||
mod from_to_bytes;
|
|
||||||
#[cfg(feature = "msgpack_serde")]
|
|
||||||
mod msgpack_serde;
|
|
||||||
#[cfg(feature = "prost")]
|
|
||||||
mod prost;
|
|
||||||
|
|
||||||
#[cfg(feature = "bincode_serde")]
|
|
||||||
pub use bincode_serde::*;
|
|
||||||
#[allow(unused_imports)]
|
|
||||||
pub use from_to_bytes::*;
|
|
||||||
#[cfg(feature = "msgpack_serde")]
|
|
||||||
pub use msgpack_serde::*;
|
|
||||||
#[cfg(feature = "prost")]
|
|
||||||
pub use prost::*;
|
|
|
@ -1,45 +0,0 @@
|
||||||
use crate::utils::{Decoder, Encoder};
|
|
||||||
|
|
||||||
/// A codec that relies on `rmp-serde` to encode data in the msgpack format.
|
|
||||||
///
|
|
||||||
/// This is only available with the **`msgpack` feature** enabled.
|
|
||||||
pub struct MsgpackSerdeCodec;
|
|
||||||
|
|
||||||
impl<T: serde::Serialize> Encoder<T> for MsgpackSerdeCodec {
|
|
||||||
type Error = rmp_serde::encode::Error;
|
|
||||||
type Encoded = Vec<u8>;
|
|
||||||
|
|
||||||
fn encode(val: &T) -> Result<Self::Encoded, Self::Error> {
|
|
||||||
rmp_serde::to_vec(val)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: serde::de::DeserializeOwned> Decoder<T> for MsgpackSerdeCodec {
|
|
||||||
type Error = rmp_serde::decode::Error;
|
|
||||||
type Encoded = [u8];
|
|
||||||
|
|
||||||
fn decode(val: &Self::Encoded) -> Result<T, Self::Error> {
|
|
||||||
rmp_serde::from_slice(val)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_msgpack_codec() {
|
|
||||||
#[derive(Clone, Debug, PartialEq, serde::Serialize, serde::Deserialize)]
|
|
||||||
struct Test {
|
|
||||||
s: String,
|
|
||||||
i: i32,
|
|
||||||
}
|
|
||||||
let t = Test {
|
|
||||||
s: String::from("party time 🎉"),
|
|
||||||
i: 42,
|
|
||||||
};
|
|
||||||
let enc = MsgpackSerdeCodec::encode(&t).unwrap();
|
|
||||||
let dec: Test = MsgpackSerdeCodec::decode(&enc).unwrap();
|
|
||||||
assert_eq!(dec, t);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,76 +0,0 @@
|
||||||
use crate::utils::{Decoder, Encoder};
|
|
||||||
|
|
||||||
/// A codec for storing ProtoBuf messages that relies on [`prost`](https://github.com/tokio-rs/prost) to parse.
|
|
||||||
///
|
|
||||||
/// [Protocol buffers](https://protobuf.dev/overview/) is a serialisation format useful for
|
|
||||||
/// long-term storage. It provides semantics for versioning that are not present in JSON or other
|
|
||||||
/// formats. [`prost`] is a Rust implementation of Protocol Buffers.
|
|
||||||
///
|
|
||||||
/// This codec uses [`prost`](https://github.com/tokio-rs/prost) to encode the message into a byte stream.
|
|
||||||
/// To use it with local storage in the example below we wrap it with [`Base64`] to represent the bytes as a string.
|
|
||||||
///
|
|
||||||
/// ## Example
|
|
||||||
/// ```
|
|
||||||
/// # use leptos::*;
|
|
||||||
/// # use leptos_use::storage::{StorageType, use_local_storage, use_session_storage, use_storage, UseStorageOptions};
|
|
||||||
/// # use leptos_use::utils::{Base64, ProstCodec};
|
|
||||||
/// #
|
|
||||||
/// # pub fn Demo() -> impl IntoView {
|
|
||||||
/// // Primitive types:
|
|
||||||
/// let (get, set, remove) = use_local_storage::<i32, Base64<ProstCodec>>("my-key");
|
|
||||||
///
|
|
||||||
/// // Structs:
|
|
||||||
/// #[derive(Clone, PartialEq, prost::Message)]
|
|
||||||
/// pub struct MyState {
|
|
||||||
/// #[prost(string, tag = "1")]
|
|
||||||
/// pub hello: String,
|
|
||||||
/// }
|
|
||||||
/// let (get, set, remove) = use_local_storage::<MyState, Base64<ProstCodec>>("my-struct-key");
|
|
||||||
/// # view! { }
|
|
||||||
/// # }
|
|
||||||
/// ```
|
|
||||||
///
|
|
||||||
/// Note: we've defined and used the `prost` attribute here for brevity. Alternate usage would be to
|
|
||||||
/// describe the message in a .proto file and use [`prost_build`](https://docs.rs/prost-build) to
|
|
||||||
/// auto-generate the Rust code.
|
|
||||||
pub struct ProstCodec;
|
|
||||||
|
|
||||||
impl<T: prost::Message> Encoder<T> for ProstCodec {
|
|
||||||
type Error = ();
|
|
||||||
type Encoded = Vec<u8>;
|
|
||||||
|
|
||||||
fn encode(val: &T) -> Result<Self::Encoded, Self::Error> {
|
|
||||||
let buf = val.encode_to_vec();
|
|
||||||
Ok(buf)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: prost::Message + Default> Decoder<T> for ProstCodec {
|
|
||||||
type Error = prost::DecodeError;
|
|
||||||
type Encoded = [u8];
|
|
||||||
|
|
||||||
fn decode(val: &Self::Encoded) -> Result<T, Self::Error> {
|
|
||||||
T::decode(val)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_prost_codec() {
|
|
||||||
#[derive(Clone, PartialEq, prost::Message)]
|
|
||||||
struct Test {
|
|
||||||
#[prost(string, tag = "1")]
|
|
||||||
s: String,
|
|
||||||
#[prost(int32, tag = "2")]
|
|
||||||
i: i32,
|
|
||||||
}
|
|
||||||
let t = Test {
|
|
||||||
s: String::from("party time 🎉"),
|
|
||||||
i: 42,
|
|
||||||
};
|
|
||||||
assert_eq!(ProstCodec::decode(&ProstCodec::encode(&t).unwrap()), Ok(t));
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,108 +0,0 @@
|
||||||
use crate::utils::{Decoder, Encoder};
|
|
||||||
use thiserror::Error;
|
|
||||||
|
|
||||||
pub trait IsBinary<T, E: ?Sized> {
|
|
||||||
fn is_binary() -> bool;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<D, T> IsBinary<T, [u8]> for D
|
|
||||||
where
|
|
||||||
D: Decoder<T, Encoded = [u8]>,
|
|
||||||
{
|
|
||||||
fn is_binary() -> bool {
|
|
||||||
true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<D, T> IsBinary<T, str> for D
|
|
||||||
where
|
|
||||||
D: Decoder<T, Encoded = str>,
|
|
||||||
{
|
|
||||||
fn is_binary() -> bool {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Error)]
|
|
||||||
pub enum HybridCoderError<E> {
|
|
||||||
#[error("Not implemented: {0}")]
|
|
||||||
NotImplemented(&'static str),
|
|
||||||
#[error("Decoding error")]
|
|
||||||
Coder(#[from] E),
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait HybridDecoder<T, E: ?Sized> {
|
|
||||||
type Error;
|
|
||||||
|
|
||||||
fn decode_str(_val: &str) -> Result<T, HybridCoderError<Self::Error>> {
|
|
||||||
Err(HybridCoderError::NotImplemented(
|
|
||||||
"You're trying to decode from a string. This codec is binary.",
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn decode_bin(_val: &[u8]) -> Result<T, HybridCoderError<Self::Error>> {
|
|
||||||
Err(HybridCoderError::NotImplemented(
|
|
||||||
"You're trying to decode from a byte slice. This codec is a string codec.",
|
|
||||||
))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T, D> HybridDecoder<T, [u8]> for D
|
|
||||||
where
|
|
||||||
D: Decoder<T, Encoded = [u8]>,
|
|
||||||
{
|
|
||||||
type Error = D::Error;
|
|
||||||
|
|
||||||
fn decode_bin(val: &[u8]) -> Result<T, HybridCoderError<Self::Error>> {
|
|
||||||
Ok(D::decode(val)?)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T, D> HybridDecoder<T, str> for D
|
|
||||||
where
|
|
||||||
D: Decoder<T, Encoded = str>,
|
|
||||||
{
|
|
||||||
type Error = D::Error;
|
|
||||||
|
|
||||||
fn decode_str(val: &str) -> Result<T, HybridCoderError<Self::Error>> {
|
|
||||||
Ok(D::decode(val)?)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait HybridEncoder<T, E> {
|
|
||||||
type Error;
|
|
||||||
|
|
||||||
fn encode_str(_val: &T) -> Result<String, HybridCoderError<Self::Error>> {
|
|
||||||
Err(HybridCoderError::NotImplemented(
|
|
||||||
"You're trying to encode into a string. This codec is binary.",
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn encode_bin(_val: &T) -> Result<Vec<u8>, HybridCoderError<Self::Error>> {
|
|
||||||
Err(HybridCoderError::NotImplemented(
|
|
||||||
"You're trying to encode into a byte vec. This codec is a string codec.",
|
|
||||||
))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T, E> HybridEncoder<T, Vec<u8>> for E
|
|
||||||
where
|
|
||||||
E: Encoder<T, Encoded = Vec<u8>>,
|
|
||||||
{
|
|
||||||
type Error = E::Error;
|
|
||||||
|
|
||||||
fn encode_bin(val: &T) -> Result<Vec<u8>, HybridCoderError<Self::Error>> {
|
|
||||||
Ok(E::encode(val)?)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T, E> HybridEncoder<T, String> for E
|
|
||||||
where
|
|
||||||
E: Encoder<T, Encoded = String>,
|
|
||||||
{
|
|
||||||
type Error = E::Error;
|
|
||||||
|
|
||||||
fn encode_str(val: &T) -> Result<String, HybridCoderError<Self::Error>> {
|
|
||||||
Ok(E::encode(val)?)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,32 +0,0 @@
|
||||||
mod bin;
|
|
||||||
mod hybrid;
|
|
||||||
mod string;
|
|
||||||
|
|
||||||
pub use bin::*;
|
|
||||||
pub use hybrid::*;
|
|
||||||
pub use string::*;
|
|
||||||
use thiserror::Error;
|
|
||||||
|
|
||||||
/// Trait every encoder must implement.
|
|
||||||
pub trait Encoder<T>: 'static {
|
|
||||||
type Error;
|
|
||||||
type Encoded;
|
|
||||||
|
|
||||||
fn encode(val: &T) -> Result<Self::Encoded, Self::Error>;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Trait every decoder must implement.
|
|
||||||
pub trait Decoder<T>: 'static {
|
|
||||||
type Error;
|
|
||||||
type Encoded: ?Sized;
|
|
||||||
|
|
||||||
fn decode(val: &Self::Encoded) -> Result<T, Self::Error>;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Error, Debug)]
|
|
||||||
pub enum CodecError<E, D> {
|
|
||||||
#[error("failed to encode: {0}")]
|
|
||||||
Encode(E),
|
|
||||||
#[error("failed to decode: {0}")]
|
|
||||||
Decode(D),
|
|
||||||
}
|
|
|
@ -1,67 +0,0 @@
|
||||||
use crate::utils::{Decoder, Encoder};
|
|
||||||
use base64::Engine;
|
|
||||||
use thiserror::Error;
|
|
||||||
|
|
||||||
/// Wraps a binary codec and make it a string codec by representing the binary data as a base64
|
|
||||||
/// string.
|
|
||||||
///
|
|
||||||
/// Only available with the **`base64` feature** enabled.
|
|
||||||
///
|
|
||||||
/// Example:
|
|
||||||
///
|
|
||||||
/// ```
|
|
||||||
/// # use leptos_use::utils::{Base64, MsgpackSerdeCodec, Encoder, Decoder};
|
|
||||||
/// # use serde::{Serialize, Deserialize};
|
|
||||||
/// #
|
|
||||||
/// #[derive(Serialize, Deserialize, PartialEq, Debug)]
|
|
||||||
/// struct MyState {
|
|
||||||
/// chicken_count: u32,
|
|
||||||
/// egg_count: u32,
|
|
||||||
/// farm_name: String,
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// let original_value = MyState {
|
|
||||||
/// chicken_count: 10,
|
|
||||||
/// egg_count: 20,
|
|
||||||
/// farm_name: "My Farm".to_owned(),
|
|
||||||
/// };
|
|
||||||
///
|
|
||||||
/// let encoded: String = Base64::<MsgpackSerdeCodec>::encode(&original_value).unwrap();
|
|
||||||
/// let decoded: MyState = Base64::<MsgpackSerdeCodec>::decode(&encoded).unwrap();
|
|
||||||
///
|
|
||||||
/// assert_eq!(decoded, original_value);
|
|
||||||
/// ```
|
|
||||||
pub struct Base64<C>(C);
|
|
||||||
|
|
||||||
#[derive(Error, Debug, PartialEq)]
|
|
||||||
pub enum Base64DecodeError<Err> {
|
|
||||||
#[error("failed to decode base64: {0}")]
|
|
||||||
DecodeBase64(#[from] base64::DecodeError),
|
|
||||||
#[error("failed to decode: {0}")]
|
|
||||||
Decoder(Err),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T, E> Encoder<T> for Base64<E>
|
|
||||||
where
|
|
||||||
E: Encoder<T, Encoded = Vec<u8>>,
|
|
||||||
{
|
|
||||||
type Error = E::Error;
|
|
||||||
type Encoded = String;
|
|
||||||
|
|
||||||
fn encode(val: &T) -> Result<Self::Encoded, Self::Error> {
|
|
||||||
Ok(base64::engine::general_purpose::STANDARD.encode(E::encode(val)?))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T, D> Decoder<T> for Base64<D>
|
|
||||||
where
|
|
||||||
D: Decoder<T, Encoded = [u8]>,
|
|
||||||
{
|
|
||||||
type Error = Base64DecodeError<D::Error>;
|
|
||||||
type Encoded = str;
|
|
||||||
|
|
||||||
fn decode(val: &Self::Encoded) -> Result<T, Self::Error> {
|
|
||||||
let buf = base64::engine::general_purpose::STANDARD.decode(val)?;
|
|
||||||
D::decode(&buf).map_err(Base64DecodeError::Decoder)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,51 +0,0 @@
|
||||||
use crate::utils::{Decoder, Encoder};
|
|
||||||
use std::str::FromStr;
|
|
||||||
|
|
||||||
/// A string codec that relies on [`FromStr`] and [`ToString`]. It can encode anything that
|
|
||||||
/// implements [`ToString`] and decode anything that implements [`FromStr`].
|
|
||||||
///
|
|
||||||
/// This makes simple key / value easy to use for primitive types. It is also useful for encoding
|
|
||||||
/// simply data structures without depending on third party crates like serde and serde_json.
|
|
||||||
///
|
|
||||||
/// ## Example
|
|
||||||
/// ```
|
|
||||||
/// # use leptos::*;
|
|
||||||
/// # use leptos_use::storage::{StorageType, use_local_storage, use_session_storage, use_storage, UseStorageOptions};
|
|
||||||
/// # use leptos_use::utils::FromToStringCodec;
|
|
||||||
/// #
|
|
||||||
/// # pub fn Demo() -> impl IntoView {
|
|
||||||
/// let (get, set, remove) = use_local_storage::<i32, FromToStringCodec>("my-key");
|
|
||||||
/// # view! { }
|
|
||||||
/// # }
|
|
||||||
/// ```
|
|
||||||
pub struct FromToStringCodec;
|
|
||||||
|
|
||||||
impl<T: ToString> Encoder<T> for FromToStringCodec {
|
|
||||||
type Error = ();
|
|
||||||
type Encoded = String;
|
|
||||||
|
|
||||||
fn encode(val: &T) -> Result<String, Self::Error> {
|
|
||||||
Ok(val.to_string())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: FromStr> Decoder<T> for FromToStringCodec {
|
|
||||||
type Error = T::Err;
|
|
||||||
type Encoded = str;
|
|
||||||
|
|
||||||
fn decode(val: &Self::Encoded) -> Result<T, Self::Error> {
|
|
||||||
T::from_str(val)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_string_codec() {
|
|
||||||
let s = String::from("party time 🎉");
|
|
||||||
assert_eq!(FromToStringCodec::encode(&s), Ok(s.clone()));
|
|
||||||
assert_eq!(FromToStringCodec::decode(&s), Ok(s));
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,67 +0,0 @@
|
||||||
use crate::utils::{Decoder, Encoder};
|
|
||||||
|
|
||||||
/// A codec for encoding JSON messages that relies on [`serde_json`].
|
|
||||||
///
|
|
||||||
/// Only available with the **`json` feature** enabled.
|
|
||||||
///
|
|
||||||
/// ## Example
|
|
||||||
///
|
|
||||||
/// ```
|
|
||||||
/// # use leptos::*;
|
|
||||||
/// # use leptos_use::storage::{StorageType, use_local_storage, use_session_storage, use_storage, UseStorageOptions};
|
|
||||||
/// # use serde::{Deserialize, Serialize};
|
|
||||||
/// # use leptos_use::utils::JsonSerdeCodec;
|
|
||||||
/// #
|
|
||||||
/// # pub fn Demo() -> impl IntoView {
|
|
||||||
/// // Primitive types:
|
|
||||||
/// let (get, set, remove) = use_local_storage::<i32, JsonSerdeCodec>("my-key");
|
|
||||||
///
|
|
||||||
/// // Structs:
|
|
||||||
/// #[derive(Serialize, Deserialize, Clone, Default, PartialEq)]
|
|
||||||
/// pub struct MyState {
|
|
||||||
/// pub hello: String,
|
|
||||||
/// }
|
|
||||||
/// let (get, set, remove) = use_local_storage::<MyState, JsonSerdeCodec>("my-struct-key");
|
|
||||||
/// # view! { }
|
|
||||||
/// # }
|
|
||||||
/// ```
|
|
||||||
pub struct JsonSerdeCodec;
|
|
||||||
|
|
||||||
impl<T: serde::Serialize> Encoder<T> for JsonSerdeCodec {
|
|
||||||
type Error = serde_json::Error;
|
|
||||||
type Encoded = String;
|
|
||||||
|
|
||||||
fn encode(val: &T) -> Result<Self::Encoded, Self::Error> {
|
|
||||||
serde_json::to_string(val)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: serde::de::DeserializeOwned> Decoder<T> for JsonSerdeCodec {
|
|
||||||
type Error = serde_json::Error;
|
|
||||||
type Encoded = str;
|
|
||||||
|
|
||||||
fn decode(val: &Self::Encoded) -> Result<T, Self::Error> {
|
|
||||||
serde_json::from_str(val)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_json_codec() {
|
|
||||||
#[derive(Clone, Debug, PartialEq, serde::Serialize, serde::Deserialize)]
|
|
||||||
struct Test {
|
|
||||||
s: String,
|
|
||||||
i: i32,
|
|
||||||
}
|
|
||||||
let t = Test {
|
|
||||||
s: String::from("party time 🎉"),
|
|
||||||
i: 42,
|
|
||||||
};
|
|
||||||
let enc = JsonSerdeCodec::encode(&t).unwrap();
|
|
||||||
let dec: Test = JsonSerdeCodec::decode(&enc).unwrap();
|
|
||||||
assert_eq!(dec, t);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,13 +0,0 @@
|
||||||
#[cfg(feature = "base64")]
|
|
||||||
mod base64;
|
|
||||||
mod from_to_string;
|
|
||||||
#[cfg(feature = "json_serde")]
|
|
||||||
mod json_serde;
|
|
||||||
mod option;
|
|
||||||
|
|
||||||
#[cfg(feature = "base64")]
|
|
||||||
pub use base64::*;
|
|
||||||
pub use from_to_string::*;
|
|
||||||
#[cfg(feature = "json_serde")]
|
|
||||||
pub use json_serde::*;
|
|
||||||
pub use option::*;
|
|
|
@ -1,45 +0,0 @@
|
||||||
use crate::utils::{Decoder, Encoder};
|
|
||||||
|
|
||||||
/// Wraps a string codec that encodes `T` to create a codec that encodes `Option<T>`.
|
|
||||||
///
|
|
||||||
/// Example:
|
|
||||||
///
|
|
||||||
/// ```
|
|
||||||
/// # use leptos_use::utils::{OptionCodec, FromToStringCodec, Encoder, Decoder};
|
|
||||||
/// #
|
|
||||||
/// let original_value = Some(4);
|
|
||||||
/// let encoded = OptionCodec::<FromToStringCodec>::encode(&original_value).unwrap();
|
|
||||||
/// let decoded = OptionCodec::<FromToStringCodec>::decode(&encoded).unwrap();
|
|
||||||
///
|
|
||||||
/// assert_eq!(decoded, original_value);
|
|
||||||
/// ```
|
|
||||||
pub struct OptionCodec<C>(C);
|
|
||||||
|
|
||||||
impl<T, E> Encoder<Option<T>> for OptionCodec<E>
|
|
||||||
where
|
|
||||||
E: Encoder<T, Encoded = String>,
|
|
||||||
{
|
|
||||||
type Error = E::Error;
|
|
||||||
type Encoded = String;
|
|
||||||
|
|
||||||
fn encode(val: &Option<T>) -> Result<String, Self::Error> {
|
|
||||||
match val {
|
|
||||||
Some(val) => Ok(format!("~<|Some|>~{}", E::encode(val)?)),
|
|
||||||
None => Ok("~<|None|>~".to_owned()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T, D> Decoder<Option<T>> for OptionCodec<D>
|
|
||||||
where
|
|
||||||
D: Decoder<T, Encoded = str>,
|
|
||||||
{
|
|
||||||
type Error = D::Error;
|
|
||||||
type Encoded = str;
|
|
||||||
|
|
||||||
fn decode(str: &Self::Encoded) -> Result<Option<T>, Self::Error> {
|
|
||||||
str.strip_prefix("~<|Some|>~")
|
|
||||||
.map(|v| D::decode(v))
|
|
||||||
.transpose()
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,4 +1,3 @@
|
||||||
mod codecs;
|
|
||||||
mod filters;
|
mod filters;
|
||||||
mod is;
|
mod is;
|
||||||
mod js;
|
mod js;
|
||||||
|
@ -7,7 +6,6 @@ mod pausable;
|
||||||
mod signal_filtered;
|
mod signal_filtered;
|
||||||
mod use_derive_signal;
|
mod use_derive_signal;
|
||||||
|
|
||||||
pub use codecs::*;
|
|
||||||
pub use filters::*;
|
pub use filters::*;
|
||||||
pub use is::*;
|
pub use is::*;
|
||||||
pub(crate) use js_value_from_to_string::*;
|
pub(crate) use js_value_from_to_string::*;
|
||||||
|
|
Loading…
Add table
Reference in a new issue