1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
use anyhow::Result as AnyResult;
use http::{header::HeaderName, HeaderValue, StatusCode};
use std::{
    fmt::{self, Debug},
    ops::Deref,
};

macro_rules! impl_callback {
    ($name:ident, $name_str:literal, $callback:path) => {
        impl<'r> $name<'r> {
            /// 创建回调函数
            #[inline]
            pub fn new(callback: impl $callback + Send + Sync + 'r) -> Self {
                Self::Boxed(Box::new(callback))
            }

            /// 创建回调函数的引用
            #[inline]
            pub fn reference(callback: &'r (dyn $callback + Send + Sync + 'r)) -> Self {
                Self::Referenced(callback)
            }
        }

        impl<'r, T: $callback + Send + Sync + 'r> From<T> for $name<'r> {
            #[inline]
            fn from(callback: T) -> Self {
                Self::new(callback)
            }
        }

        impl<'r> Deref for $name<'r> {
            type Target = (dyn $callback + Send + Sync + 'r);

            #[inline]
            fn deref(&self) -> &Self::Target {
                match self {
                    Self::Boxed(callback) => callback.deref(),
                    Self::Referenced(callback) => callback,
                }
            }
        }

        impl Debug for $name<'_> {
            #[inline]
            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
                f.debug_struct($name_str).finish()
            }
        }
    };
}

/// 上传进度回调
pub enum OnProgressCallback<'r> {
    /// 用 Box 包装的上传进度回调
    Boxed(Box<dyn Fn(TransferProgressInfo) -> AnyResult<()> + Send + Sync + 'r>),
    /// 上传进度回调的引用
    Referenced(&'r (dyn Fn(TransferProgressInfo) -> AnyResult<()> + Send + Sync + 'r)),
}
impl_callback!(OnProgressCallback, "OnProgressCallback", Fn(TransferProgressInfo) -> AnyResult<()>);

pub(super) type OnProgress<'r> = &'r (dyn Fn(TransferProgressInfo<'_>) -> AnyResult<()> + Send + Sync + 'r);

/// 响应状态回调
pub enum OnStatusCodeCallback<'r> {
    /// 用 Box 包装的响应状态回调
    Boxed(Box<dyn Fn(StatusCode) -> AnyResult<()> + Send + Sync + 'r>),
    /// 响应状态回调的引用
    Referenced(&'r (dyn Fn(StatusCode) -> AnyResult<()> + Send + Sync + 'r)),
}
impl_callback!(OnStatusCodeCallback, "OnStatusCodeCallback", Fn(StatusCode) -> AnyResult<()>);

pub(super) type OnStatusCode<'r> = &'r (dyn Fn(StatusCode) -> AnyResult<()> + Send + Sync + 'r);

type OnHeaderCallbackFn<'r> = Box<dyn Fn(&HeaderName, &HeaderValue) -> AnyResult<()> + Send + Sync + 'r>;
type OnHeaderCallbackFnRef<'r> = &'r (dyn Fn(&HeaderName, &HeaderValue) -> AnyResult<()> + Send + Sync + 'r);

/// 接受到响应 Header 回调
pub enum OnHeaderCallback<'r> {
    /// 用 Box 包装的接受到响应 Header 回调
    Boxed(OnHeaderCallbackFn<'r>),
    /// 接受到响应 Header 回调的引用
    Referenced(OnHeaderCallbackFnRef<'r>),
}
impl_callback!(OnHeaderCallback, "OnHeaderCallback", Fn(&HeaderName, &HeaderValue) -> AnyResult<()>);

pub(super) type OnHeader<'r> = &'r (dyn Fn(&HeaderName, &HeaderValue) -> AnyResult<()> + Send + Sync + 'r);

/// 数据传输进度信息
#[derive(Debug, Clone, Copy)]
pub struct TransferProgressInfo<'b> {
    transferred_bytes: u64,
    total_bytes: u64,
    body: &'b [u8],
}

impl<'b> TransferProgressInfo<'b> {
    /// 创建数据传输进度信息
    #[inline]
    pub fn new(transferred_bytes: u64, total_bytes: u64, body: &'b [u8]) -> Self {
        Self {
            transferred_bytes,
            total_bytes,
            body,
        }
    }

    /// 获取已经传输的数据量
    ///
    /// 单位为字节
    #[inline]
    pub fn transferred_bytes(&self) -> u64 {
        self.transferred_bytes
    }

    /// 获取总共需要传输的数据量
    ///
    /// 单位为字节
    #[inline]
    pub fn total_bytes(&self) -> u64 {
        self.total_bytes
    }

    /// 获取当前传输的数据
    #[inline]
    pub fn body(&self) -> &[u8] {
        self.body
    }
}