Coverage Report

Created: 2026-07-21 15:28

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/build/source/nativelink-store/src/redis_utils/ft_cursor_read.rs
Line
Count
Source
1
// Copyright 2025 The NativeLink Authors. All rights reserved.
2
//
3
// Licensed under the Functional Source License, Version 1.1, Apache 2.0 Future License (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
6
//
7
//    See LICENSE file for details
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14
15
use redis::aio::ConnectionLike;
16
use redis::{ErrorKind, RedisError, Value};
17
18
use crate::redis_utils::aggregate_types::RedisCursorData;
19
20
1
pub(crate) async fn ft_cursor_read<C>(
21
1
    connection_manager: &mut C,
22
1
    index: String,
23
1
    cursor_id: u64,
24
1
) -> Result<RedisCursorData, RedisError>
25
1
where
26
1
    C: ConnectionLike + Send,
27
1
{
28
1
    let mut cmd = redis::cmd("ft.cursor");
29
1
    let ft_cursor_cmd = cmd.arg("read").arg(index).cursor_arg(cursor_id);
30
1
    let data = ft_cursor_cmd
31
1
        .to_owned()
32
1
        .query_async::<Value>(connection_manager)
33
1
        .await
?0
;
34
1
    let Value::Array(value) = data else {
35
0
        return Err(RedisError::from((ErrorKind::Parse, "Expected array")));
36
    };
37
1
    if value.len() < 2 {
38
0
        return Err(RedisError::from((
39
0
            ErrorKind::Parse,
40
0
            "Expected at least 2 elements",
41
0
        )));
42
1
    }
43
1
    let mut value = value.into_iter();
44
1
    let Value::Array(data_ary) = value.next().unwrap() else {
45
0
        return Err(RedisError::from((ErrorKind::Parse, "Non map item")));
46
    };
47
1
    if data_ary.is_empty() {
48
0
        return Err(RedisError::from((
49
0
            ErrorKind::Parse,
50
0
            "Expected at least 1 element in data array",
51
0
        )));
52
1
    }
53
1
    let Value::Int(new_cursor_id) = value.next().unwrap() else {
54
0
        return Err(RedisError::from((
55
0
            ErrorKind::Parse,
56
0
            "Expected cursor id as second element",
57
0
        )));
58
    };
59
60
1
    Ok(RedisCursorData {
61
1
        // this should generally be impossible, but -1 provides a decent "obviously bad" value just in case
62
1
        total: i64::try_from(data_ary.len()).unwrap_or(-1),
63
1
        cursor: new_cursor_id as u64,
64
1
        data: data_ary.into(),
65
1
    })
66
1
}