use cosmwasm_schema::{cw_serde, QueryResponses};
use cosmwasm_std::{Binary, Uint128};
use derive_builder::Builder;
use enum_iterator::{all, Sequence};
pub type ObjectId = String;
pub type Cursor = String;
#[cw_serde]
pub struct InstantiateMsg {
pub bucket: String,
#[serde(default)]
pub config: BucketConfig,
#[serde(default)]
pub limits: BucketLimits,
#[serde(default)]
pub pagination: PaginationConfig,
}
#[cw_serde]
pub enum ExecuteMsg {
StoreObject {
data: Binary,
pin: bool,
compression_algorithm: Option<CompressionAlgorithm>,
},
ForgetObject { id: ObjectId },
PinObject { id: ObjectId },
UnpinObject { id: ObjectId },
}
#[cw_serde]
#[derive(QueryResponses)]
pub enum QueryMsg {
#[returns(BucketResponse)]
Bucket {},
#[returns(ObjectResponse)]
Object {
id: ObjectId,
},
#[returns(ObjectsResponse)]
Objects {
address: Option<String>,
first: Option<u32>,
after: Option<Cursor>,
},
#[returns(Binary)]
ObjectData {
id: ObjectId,
},
#[returns(ObjectPinsResponse)]
ObjectPins {
id: ObjectId,
first: Option<u32>,
after: Option<Cursor>,
},
}
#[cw_serde]
pub struct PageInfo {
pub has_next_page: bool,
pub cursor: Cursor,
}
#[cw_serde]
pub struct BucketResponse {
pub name: String,
pub config: BucketConfig,
pub limits: BucketLimits,
pub pagination: PaginationConfig,
pub stat: BucketStat,
}
#[cw_serde]
#[derive(Copy, Eq, PartialOrd, Sequence)]
pub enum CompressionAlgorithm {
Passthrough,
Snappy,
Lzma,
}
#[cw_serde]
#[derive(Copy)]
pub enum HashAlgorithm {
MD5,
Sha224,
Sha256,
Sha384,
Sha512,
}
impl Default for HashAlgorithm {
fn default() -> Self {
Self::Sha256
}
}
#[cw_serde]
#[derive(Builder)]
#[builder(default, setter(into, strip_option))]
pub struct BucketConfig {
#[serde(default)]
pub hash_algorithm: HashAlgorithm,
#[serde(default = "CompressionAlgorithm::values")]
pub accepted_compression_algorithms: Vec<CompressionAlgorithm>,
}
impl Default for BucketConfig {
fn default() -> Self {
Self {
hash_algorithm: Default::default(),
accepted_compression_algorithms: CompressionAlgorithm::values(),
}
}
}
impl CompressionAlgorithm {
pub fn values() -> Vec<CompressionAlgorithm> {
all::<CompressionAlgorithm>().collect::<Vec<_>>()
}
}
#[cw_serde]
#[derive(Default, Builder)]
#[builder(default, setter(into, strip_option))]
pub struct BucketLimits {
pub max_total_size: Option<Uint128>,
pub max_objects: Option<Uint128>,
pub max_object_size: Option<Uint128>,
pub max_object_pins: Option<Uint128>,
}
#[cw_serde]
#[derive(Builder)]
#[builder(default, setter(strip_option))]
pub struct PaginationConfig {
#[serde(default = "PaginationConfig::default_page_max_size")]
pub max_page_size: u32,
#[serde(default = "PaginationConfig::default_page_default_size")]
pub default_page_size: u32,
}
impl PaginationConfig {
const fn default_page_max_size() -> u32 {
30
}
const fn default_page_default_size() -> u32 {
10
}
}
impl Default for PaginationConfig {
fn default() -> Self {
PaginationConfig {
max_page_size: Self::default_page_max_size(),
default_page_size: Self::default_page_default_size(),
}
}
}
#[cw_serde]
#[derive(Default, Builder)]
pub struct BucketStat {
pub size: Uint128,
pub compressed_size: Uint128,
pub object_count: Uint128,
}
#[cw_serde]
pub struct ObjectResponse {
pub id: ObjectId,
pub owner: String,
pub is_pinned: bool,
pub size: Uint128,
pub compressed_size: Uint128,
pub compression_algorithm: CompressionAlgorithm,
}
#[cw_serde]
pub struct ObjectsResponse {
pub data: Vec<ObjectResponse>,
pub page_info: PageInfo,
}
#[cw_serde]
pub struct ObjectPinsResponse {
pub data: Vec<String>,
pub page_info: PageInfo,
}
#[cfg(test)]
mod tests {
use crate::msg::CompressionAlgorithm::{Lzma, Passthrough, Snappy};
use crate::msg::HashAlgorithm::Sha256;
use crate::msg::{BucketConfig, BucketLimits, InstantiateMsg, PaginationConfig};
use schemars::_serde_json;
#[test]
fn pagination_config_default_deserialization() {
let json = r#"
{}
"#;
let page: PaginationConfig = _serde_json::from_str(json).unwrap();
assert_eq!(page.max_page_size, 30);
assert_eq!(page.default_page_size, 10);
}
#[test]
fn bucket_config_default_deserialization() {
let json = r#"
{}
"#;
let config: BucketConfig = _serde_json::from_str(json).unwrap();
assert_eq!(config.hash_algorithm, Sha256);
assert_eq!(
config.accepted_compression_algorithms,
vec![Passthrough, Snappy, Lzma]
);
}
#[test]
fn bucket_limit_default_deserialization() {
let json = r#"
{}
"#;
let limits: BucketLimits = _serde_json::from_str(json).unwrap();
assert_eq!(limits.max_object_pins, None);
assert_eq!(limits.max_objects, None);
assert_eq!(limits.max_object_size, None);
assert_eq!(limits.max_total_size, None);
}
#[test]
fn instantiate_default_deserialization() {
let json = r#"
{
"bucket": "foo"
}
"#;
let msg: InstantiateMsg = _serde_json::from_str(json).unwrap();
assert_eq!(msg.pagination.max_page_size, 30);
assert_eq!(msg.pagination.default_page_size, 10);
assert_eq!(msg.config.hash_algorithm, Sha256);
assert_eq!(
msg.config.accepted_compression_algorithms,
vec![Passthrough, Snappy, Lzma]
);
assert_eq!(msg.limits.max_object_pins, None);
assert_eq!(msg.limits.max_objects, None);
assert_eq!(msg.limits.max_object_size, None);
assert_eq!(msg.limits.max_total_size, None);
}
}