Iros
 
Loading...
Searching...
No Matches
userspace_buffer.h
Go to the documentation of this file.
1#pragma once
2
3#include "di/assert/prelude.h"
5#include "iris/core/error.h"
7
8namespace iris {
9template<di::concepts::ImplicitLifetime T>
10class UserspaceBuffer {
11private:
12 using Storage = di::meta::RemoveCV<T>;
13
14 constexpr static bool is_const = di::concepts::Const<T>;
15 constexpr static bool is_byte = di::concepts::SameAs<Storage, byte>;
16
17 explicit UserspaceBuffer(T* pointer, usize length) : m_buffer(pointer, length) {}
18
19public:
20 static auto create(T* pointer, usize length) -> Expected<UserspaceBuffer<T>> {
21 if (!validate_user_region(mm::VirtualAddress(di::to_uintptr(pointer)), length, sizeof(T))) {
23 }
24 return UserspaceBuffer<T> { pointer, length };
25 }
26
28 requires(!is_const)
29 {
30 auto to_write = di::min(data.size_bytes(), m_buffer.size_bytes());
31 TRY(copy_to_user(*di::as_bytes(data).first(to_write), reinterpret_cast<byte*>(m_buffer.data())));
32 return to_write;
33 }
34
36 auto to_read = di::min(buffer.size_bytes(), m_buffer.size_bytes());
37 TRY(copy_from_user(*di::as_bytes(m_buffer).first(to_read), reinterpret_cast<byte*>(buffer.data())));
38 return to_read;
39 }
40
42 requires(is_byte)
43 {
44 auto string = di::TransparentString {};
45 TRY(string.reserve_from_nothing(size()));
46 string.assume_size(size());
47 TRY(copy_to({ reinterpret_cast<byte*>(string.span().data()), string.size() }));
48 return string;
49 }
50
51 auto copy_to_path() const -> Expected<di::Path>
52 requires(is_byte)
53 {
54 if (size() > 4096) {
56 }
57 auto string = TRY(copy_to_string());
58 return di::Path(di::move(string));
59 }
60
61 template<usize chunk_size>
63 auto buffer = di::Array<byte, sizeof(Storage) * chunk_size> {};
64 for (auto offset : di::range(size_bytes()) | di::stride(sizeof(Storage) * chunk_size)) {
65 auto to_read = di::min(sizeof(Storage) * chunk_size, size_bytes() - offset);
66 auto userspace_buffer = reinterpret_cast<byte const*>(m_buffer.data()) + offset;
67 TRY(copy_from_user({ userspace_buffer, to_read }, buffer.data()));
68 TRY(process_chunk({ reinterpret_cast<Storage*>(buffer.data()), to_read / sizeof(Storage) }));
69 }
70 return {};
71 }
72
73 auto size() const -> usize { return m_buffer.size(); }
74 auto size_bytes() const -> usize { return m_buffer.size_bytes(); }
75 [[nodiscard]] auto empty() const -> bool { return m_buffer.empty(); }
76
77 void advance(usize offset) {
78 ASSERT_LT_EQ(offset, size_bytes());
79 m_buffer = *m_buffer.subspan(offset);
80 }
81
82private:
83 di::Span<T> m_buffer;
84};
85
86template<typename T>
89}
#define ASSERT_LT_EQ
Definition assert_binary.h:88
Definition function_ref.h:116
Definition span_forward_declaration.h:10
Definition unexpected.h:14
Definition userspace_buffer.h:10
auto copy_to_string() const -> Expected< di::TransparentString > requires(is_byte)
Definition userspace_buffer.h:41
auto empty() const -> bool
Definition userspace_buffer.h:75
auto size() const -> usize
Definition userspace_buffer.h:73
auto write(di::Span< T const > data) const -> Expected< usize > requires(!is_const)
Definition userspace_buffer.h:27
auto copy_to_path() const -> Expected< di::Path > requires(is_byte)
Definition userspace_buffer.h:51
auto copy_in_chunks(di::FunctionRef< Expected< void >(di::Span< Storage >)> process_chunk) const -> Expected< void >
Definition userspace_buffer.h:62
auto size_bytes() const -> usize
Definition userspace_buffer.h:74
auto copy_to(di::Span< Storage > buffer) const -> Expected< usize >
Definition userspace_buffer.h:35
static auto create(T *pointer, usize length) -> Expected< UserspaceBuffer< T > >
Definition userspace_buffer.h:20
void advance(usize offset)
Definition userspace_buffer.h:77
Definition language.h:18
Definition core.h:114
#define TRY
Definition monad_try.h:23
string::StringImpl< string::TransparentEncoding > TransparentString
Definition string.h:12
PathImpl< TransparentString > Path
Definition path.h:10
RemoveConst< RemoveVolatile< T > > RemoveCV
Definition core.h:57
std::byte byte
Definition byte.h:64
size_t usize
Definition integers.h:33
di::meta::Decay< decltype(T)> Tag
Definition tag_invoke.h:28
Definition zstring_parser.h:9
constexpr auto min
Definition min.h:47
constexpr auto as_bytes
Definition as_bytes.h:16
constexpr auto data
Definition data.h:51
constexpr auto to_uintptr
Definition to_uintptr.h:13
di::StrongInt< VirtualAddressTag > VirtualAddress
Definition virtual_address.h:25
Definition cxx_init.cpp:12
@ FilenameTooLong
Definition error.h:27
@ BadAddress
Definition error.h:12
auto copy_to_user(di::Span< byte const > kernel_data, byte *userspace_ptr) -> Expected< void >
Definition userspace_access.cpp:33
auto copy_from_user(di::Span< byte const > userspace_data, byte *kernel_ptr) -> Expected< void >
Definition userspace_access.cpp:42
auto tag_invoke(di::Tag< read_file >, DebugFile &, UserspaceBuffer< byte > buffer) -> di::AnySenderOf< usize >
Definition debug_file.cpp:7
auto validate_user_region(mm::VirtualAddress userspace_address, usize count, usize size) -> Expected< void >
Definition userspace_access.cpp:70
di::vocab::Expected< T, di::platform::GenericCode > Expected
Definition error.h:324
Definition in_place_template.h:5
Definition span_fixed_size.h:37