Haio
0.2.X
Homebrew Asset IO/CDN
Toggle main menu visibility
Loading...
Searching...
No Matches
haio_pipe.hpp
Go to the documentation of this file.
1
#pragma once
2
3
#include "
haio_registry.hpp
"
4
5
#include <fstream>
6
#include <iterator>
7
#include <utility>
8
9
/**
10
* lazily composed conversions, checked when the chain is built rather than when it
11
* runs. a stage is a callable returning Result<T>, and chaining two short circuits:
12
* the second never runs if the first failed, and the error rides through untouched.
13
*
14
* const auto pipeline = Decode | Convert<Color::ETC1> | Encode<Format::KTX2>;
15
* const auto result = pipeline(bytes);
16
*
17
* the names repeat those in Haio::Codecs on purpose: a stage is a value that
18
* composes, not a function that runs, so Pipe::Encode<Format::KTX2> is a thing you
19
* hold and Codecs::Encode<Format::KTX2, Color::ETC1> is a thing you call.
20
*/
21
namespace
Haio::Pipe
{
22
23
template
<
typename
Fn>
24
struct
Stage
{
25
Fn
fn
;
26
27
constexpr
auto
operator()
(
auto
&& in)
const
{
28
return
fn
(std::forward<
decltype
(in)>(in));
29
}
30
};
31
32
template
<
typename
A,
typename
B>
33
constexpr
auto
operator|
(
Stage<A>
first,
Stage<B>
second) {
34
return
Stage
{[first, second](
auto
&& in) {
35
auto
middle = first(std::forward<
decltype
(in)>(in));
36
using
Out =
decltype
(second(*std::move(middle)));
37
if
(!middle)
return
Out{std::unexpected(middle.error())};
38
return
second(*std::move(middle));
39
}};
40
}
41
42
namespace
Detail
{
43
44
inline
Blob
asBlob
(
const
Blob
& in) {
return
in; }
45
46
/** anything byte shaped enters the pipeline as a file of undecided format */
47
inline
Blob
asBlob
(
const
auto
& bytes) {
48
return
Blob
{
Format::RAW
,
Color::RGBA8888
, {}, {}, {bytes.begin(), bytes.end()}};
49
}
50
51
}
52
53
/**
54
* the bytes say what they are, nobody has to know beforehand.
55
*
56
* @todo the output is pinned to rgba8888 because a pipeline is typed and the input
57
* is not. a jpeg is natively yuv, so asking for y4m through here would go through
58
* rgb for nothing; Codecs::Decode<Format::JPEG, Color::YUV420> is the way around it.
59
*/
60
inline
constexpr
auto
Decode
=
Stage
{[](
const
auto
& in) ->
Result
<
Image<Color::RGBA8888>
> {
61
return
Haio::Decode
(
Detail::asBlob
(in));
62
}};
63
64
/** the target colour is named, the source is deduced from whatever arrives */
65
template
<Color To>
66
inline
constexpr
auto
Convert
=
Stage
{[]<
Color
From>(
Image<From>
src) ->
Result
<
Image<To>
>
67
requires
Codecs::Convertible<From, To>
{
68
return
Codecs::Convert<From, To>
(std::move(src));
69
}};
70
71
/** the container is named, the colour comes from the image in hand */
72
template
<Format F>
73
inline
constexpr
auto
Encode
=
Stage
{[]<
Color
P>(
Image<P>
src) ->
Result<Blob>
74
requires
Codecs::Encodable<F, P>
{
75
return
Codecs::Encode<F, P>
(std::move(src));
76
}};
77
78
/** the result type follows whatever the chain ends in, image or blob */
79
template
<
typename
Fn>
80
auto
operator>>
(std::istream& in,
const
Stage<Fn>
& stage) {
81
using
Out =
decltype
(stage(std::declval<
const
std::vector<uint8_t>&>()));
82
83
if
(!in)
return
Out{std::unexpected(
Error
{
ErrorCode::Io
,
"could not read input"
})};
84
85
// a directory opens as a stream without complaint and only fails on the first
86
// read, so the read itself has to be guarded and not just the open
87
std::vector<uint8_t> data;
88
try
{
89
data.assign(std::istreambuf_iterator<char>(in), std::istreambuf_iterator<char>());
90
}
catch
(
const
std::exception&) {
91
return
Out{std::unexpected(
Error
{
ErrorCode::Io
,
"could not read input"
})};
92
}
93
if
(in.bad())
return
Out{std::unexpected(
Error
{
ErrorCode::Io
,
"failed while reading input"
})};
94
95
return
stage(data);
96
}
97
98
}
99
100
namespace
Haio
{
101
102
/** the sugar: input >> pipeline >> output, with the Result surviving the chain */
103
inline
Result<void>
operator>>
(
const
Result<Blob>
& result, std::ostream& out) {
104
if
(!result)
return
std::unexpected(result.error());
105
106
out.write(
reinterpret_cast<
const
char
*
>
(result->data.data()),
107
static_cast<
std::streamsize
>
(result->data.size()));
108
if
(!out)
return
std::unexpected(
Error
{
ErrorCode::Io
,
"could not write output"
});
109
return
{};
110
}
111
112
}
Haio::Codecs::Convertible
Definition
haio_codec.hpp:237
Haio::Codecs::Encodable
Definition
haio_codec.hpp:227
haio_registry.hpp
Haio::Codecs::Convert
Result< Image< To > > Convert(Image< From >)=delete
Haio::Codecs::Encode
Result< Blob > Encode(Image< P >)=delete
Haio::Pipe::Detail
Definition
haio_pipe.hpp:42
Haio::Pipe::Detail::asBlob
Blob asBlob(const Blob &in)
Definition
haio_pipe.hpp:44
Haio::Pipe
Definition
haio_pipe.hpp:21
Haio::Pipe::operator|
constexpr auto operator|(Stage< A > first, Stage< B > second)
Definition
haio_pipe.hpp:33
Haio::Pipe::operator>>
auto operator>>(std::istream &in, const Stage< Fn > &stage)
Definition
haio_pipe.hpp:80
Haio::Pipe::Decode
constexpr auto Decode
Definition
haio_pipe.hpp:60
Haio::Pipe::Encode
constexpr auto Encode
Definition
haio_pipe.hpp:73
Haio::Pipe::Convert
constexpr auto Convert
Definition
haio_pipe.hpp:66
Haio
Definition
haio.hpp:11
Haio::operator>>
Result< void > operator>>(const Result< Blob > &result, std::ostream &out)
Definition
haio_pipe.hpp:103
Haio::Color
Color
Definition
haio_formats.hpp:106
Haio::Color::RGBA8888
@ RGBA8888
Definition
haio_formats.hpp:107
Haio::Result
std::expected< T, Error > Result
Definition
haio_codec.hpp:32
Haio::TokenKind::Decode
@ Decode
Definition
haio_pipeline.hpp:20
Haio::Format::RAW
@ RAW
Definition
haio_formats.hpp:19
Haio::ErrorCode::Io
@ Io
Definition
haio_codec.hpp:21
Haio::Blob
Definition
haio_codec.hpp:122
Haio::Error
Definition
haio_codec.hpp:26
Haio::Image
Definition
haio_codec.hpp:36
Haio::Pipe::Stage
Definition
haio_pipe.hpp:24
Haio::Pipe::Stage::operator()
constexpr auto operator()(auto &&in) const
Definition
haio_pipe.hpp:27
Haio::Pipe::Stage::fn
Fn fn
Definition
haio_pipe.hpp:25
include
haio_pipe.hpp
Generated by
1.18.0