mirror of
https://github.com/adoyle0/leptos-use.git
synced 2025-01-22 16:49:22 -05:00
fixed the codecs chapter in the book to refer to crate codee
This commit is contained in:
parent
26a2dc0e4b
commit
16a65b100d
1 changed files with 13 additions and 117 deletions
|
@ -1,9 +1,9 @@
|
||||||
# Encoding and Decoding Data
|
# Encoding and Decoding Data
|
||||||
|
|
||||||
Several functions encode and decode data for storing it and/or sending it over the network. To do this, codecs
|
Several functions encode and decode data for storing it and/or sending it over the network. To do this, codecs
|
||||||
located at [`src/utils/codecs`](https://github.com/Synphonyte/leptos-use/tree/main/src/utils/codecs) are used. They
|
from the crate [`codee`](https://docs.rs/codee/latest/codee/) are used. They
|
||||||
implement the traits [`Encoder`](https://github.com/Synphonyte/leptos-use/blob/main/src/utils/codecs/mod.rs#L9) with the
|
implement the traits [`Encoder`](https://docs.rs/codee/latest/codee/trait.Encoder.html) with the
|
||||||
method `encode` and [`Decoder`](https://github.com/Synphonyte/leptos-use/blob/main/src/utils/codecs/mod.rs#L17) with the
|
method `encode` and [`Decoder`](https://docs.rs/codee/latest/codee/trait.Decoder.html) with the
|
||||||
method `decode`.
|
method `decode`.
|
||||||
|
|
||||||
There are two types of codecs: One that encodes as binary data (`Vec[u8]`) and another type that encodes as
|
There are two types of codecs: One that encodes as binary data (`Vec[u8]`) and another type that encodes as
|
||||||
|
@ -11,26 +11,8 @@ strings (`String`). There is also an adapter
|
||||||
[`Base64`](https://github.com/Synphonyte/leptos-use/blob/main/src/utils/codecs/string/base64.rs) that can be used to
|
[`Base64`](https://github.com/Synphonyte/leptos-use/blob/main/src/utils/codecs/string/base64.rs) that can be used to
|
||||||
wrap a binary codec and make it a string codec by representing the binary data as a base64 string.
|
wrap a binary codec and make it a string codec by representing the binary data as a base64 string.
|
||||||
|
|
||||||
## Available Codecs
|
Please check the documentation of [`codee`](https://docs.rs/codee/latest/codee/) for more details and a list of all
|
||||||
|
available codecs.
|
||||||
### String Codecs
|
|
||||||
|
|
||||||
- [**`FromToStringCodec`
|
|
||||||
**](https://github.com/Synphonyte/leptos-use/blob/main/src/utils/codecs/string/from_to_string.rs)
|
|
||||||
- [**`JsonSerdeCodec`**](https://github.com/Synphonyte/leptos-use/blob/main/src/utils/codecs/string/json_serde.rs)**
|
|
||||||
|
|
||||||
### Binary Codecs
|
|
||||||
|
|
||||||
- [**`FromToBytesCodec`**](https://github.com/Synphonyte/leptos-use/blob/main/src/utils/codecs/binary/from_to_bytes.rs)
|
|
||||||
- [**`BincodeSerdeCodec`**](https://github.com/Synphonyte/leptos-use/blob/main/src/utils/codecs/binary/bincode_serde.rs)
|
|
||||||
- [**`MsgpackSerdeCodec`**](https://github.com/Synphonyte/leptos-use/blob/main/src/utils/codecs/binary/msgpack_serde.rs)
|
|
||||||
|
|
||||||
### Adapters
|
|
||||||
|
|
||||||
- [**`Base64`**](https://github.com/Synphonyte/leptos-use/blob/main/src/utils/codecs/string/base64.rs) —
|
|
||||||
Wraps a binary codec and make it a string codec by representing the binary data as a base64 string.
|
|
||||||
- [**`OptionCodec`**](https://github.com/Synphonyte/leptos-use/blob/main/src/utils/codecs/option.rs) —
|
|
||||||
Wraps a string codec that encodes `T` to create a codec that encodes `Option<T>`.
|
|
||||||
|
|
||||||
## Example
|
## Example
|
||||||
|
|
||||||
|
@ -41,6 +23,7 @@ format. Since cookies can only store strings, we have to use string codecs here.
|
||||||
# use leptos::*;
|
# use leptos::*;
|
||||||
# use leptos_use::use_cookie;
|
# use leptos_use::use_cookie;
|
||||||
# use serde::{Deserialize, Serialize};
|
# use serde::{Deserialize, Serialize};
|
||||||
|
# use codee::string::JsonCodec;
|
||||||
|
|
||||||
# #[component]
|
# #[component]
|
||||||
# pub fn App(cx: Scope) -> impl IntoView {
|
# pub fn App(cx: Scope) -> impl IntoView {
|
||||||
|
@ -57,100 +40,13 @@ let (cookie, set_cookie) = use_cookie::<MyState, JsonCodec>("my-state-cookie");
|
||||||
|
|
||||||
## Custom Codecs
|
## Custom Codecs
|
||||||
|
|
||||||
If you don't find a suitable codecs for your needs, you can implement your own; it's straightforward! If you want to
|
If you don't find a suitable codec for your needs, you can implement your own; it's straightforward!
|
||||||
create a string codec, you can look
|
If you want to create a string codec, you can look at
|
||||||
at [`JsonSerdeCodec`](https://github.com/Synphonyte/leptos-use/blob/main/src/utils/codecs/string/json_serde.rs).
|
[`JsonSerdeCodec`](https://docs.rs/codee/latest/src/codee/string/json_serde.rs.html).
|
||||||
In case it's a binary codec, have a look
|
In case it's a binary codec, have a look at
|
||||||
at [`BincodeSerdeCodec`](https://github.com/Synphonyte/leptos-use/blob/main/src/utils/codecs/binary/bincode_serde.rs).
|
[`BincodeSerdeCodec`](https://docs.rs/codee/latest/src/codee/binary/bincode_serde.rs.html).
|
||||||
|
|
||||||
## Versioning
|
## Versioning
|
||||||
|
|
||||||
Versioning is the process of handling long-term data that can outlive our code.
|
For a discussion on how to implement versioning please refer to the
|
||||||
|
[relevant section in the docs for `codee`](https://docs.rs/codee/latest/codee/index.html#versioning).
|
||||||
For example, we could have a settings struct whose members change over time. We might eventually
|
|
||||||
add timezone support, and we might then remove support for a thousands separator for numbers.
|
|
||||||
Each change results in a new possible version of the stored data. If we stored these settings
|
|
||||||
in browser storage, we would need to handle all possible versions of the data format that can
|
|
||||||
occur. If we don't offer versioning, then all settings could revert to the default every time we
|
|
||||||
encounter an old format.
|
|
||||||
|
|
||||||
How best to handle versioning depends on the codec involved:
|
|
||||||
|
|
||||||
- The `FromToStringCodec` can avoid versioning entirely by keeping
|
|
||||||
to primitive types. In our example above, we could have decomposed the settings struct into
|
|
||||||
separate timezone and number separator fields. These would be encoded as strings and stored as
|
|
||||||
two separate key-value fields in the browser rather than a single field. If a field is missing,
|
|
||||||
then the value intentionally would fall back to the default without interfering with the other
|
|
||||||
field.
|
|
||||||
|
|
||||||
- The `ProstCodec` uses [Protocol buffers](https://protobuf.dev/overview/)
|
|
||||||
designed to solve the problem of long-term storage. It provides semantics for versioning that
|
|
||||||
are not present in JSON or other formats.
|
|
||||||
|
|
||||||
- The codecs that use serde under the hood can rely on serde or by
|
|
||||||
providing their own manual version handling. See the next sections for more details.
|
|
||||||
|
|
||||||
### Rely on `serde`
|
|
||||||
|
|
||||||
A simple way to avoid complex versioning is to rely on serde's [field attributes](https://serde.rs/field-attrs.html)
|
|
||||||
such as [`serde(default)`](https://serde.rs/field-attrs.html#default)
|
|
||||||
and [`serde(rename = "...")`](https://serde.rs/field-attrs.html#rename).
|
|
||||||
|
|
||||||
### Manual Version Handling
|
|
||||||
|
|
||||||
We look at the example of the `JsonSerdeCodec` in this section.
|
|
||||||
|
|
||||||
To implement version handling, we parse the JSON generically then transform the
|
|
||||||
resulting `JsValue` before decoding it into our struct again.
|
|
||||||
|
|
||||||
Let's look at an example.
|
|
||||||
|
|
||||||
```rust,noplayground
|
|
||||||
# use leptos::*;
|
|
||||||
# use leptos_use::storage::{StorageType, use_local_storage, use_session_storage, use_storage, UseStorageOptions};
|
|
||||||
# use serde::{Deserialize, Serialize};
|
|
||||||
# use serde_json::json;
|
|
||||||
# use leptos_use::utils::{Encoder, Decoder};
|
|
||||||
#
|
|
||||||
# pub fn Demo() -> impl IntoView {
|
|
||||||
#[derive(Serialize, Deserialize, Clone, Default, PartialEq)]
|
|
||||||
pub struct MyState {
|
|
||||||
pub hello: String,
|
|
||||||
// This field was added in a later version
|
|
||||||
pub greeting: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct MyStateCodec;
|
|
||||||
|
|
||||||
impl Encoder<MyState> for MyStateCodec {
|
|
||||||
type Error = serde_json::Error;
|
|
||||||
type Encoded = String;
|
|
||||||
|
|
||||||
fn encode(val: &MyState) -> Result<Self::Encoded, Self::Error> {
|
|
||||||
serde_json::to_string(val)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Decoder<MyState> for MyStateCodec {
|
|
||||||
type Error = serde_json::Error;
|
|
||||||
type Encoded = str;
|
|
||||||
|
|
||||||
fn decode(stored_value: &Self::Encoded) -> Result<MyState, Self::Error> {
|
|
||||||
let mut val: serde_json::Value = serde_json::from_str(stored_value)?;
|
|
||||||
// add "greeting": "Hello" to the object if it's missing
|
|
||||||
if let Some(obj) = val.as_object_mut() {
|
|
||||||
if !obj.contains_key("greeting") {
|
|
||||||
obj.insert("greeting".to_string(), json!("Hello"));
|
|
||||||
}
|
|
||||||
serde_json::from_value(val)
|
|
||||||
} else {
|
|
||||||
Ok(MyState::default())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Then use it like the following just as any other codec.
|
|
||||||
let (get, set, remove) = use_local_storage::<MyState, MyStateCodec>("my-struct-key");
|
|
||||||
# view! { }
|
|
||||||
# }
|
|
||||||
```
|
|
Loading…
Add table
Reference in a new issue