• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

moonbitlang / x / 301

10 Dec 2024 06:19AM UTC coverage: 85.204% (-2.6%) from 87.841%
301

Pull #78

github

web-flow
Merge b830031f4 into 91f0fdf48
Pull Request #78: feat: new package encoding

105 of 161 new or added lines in 3 files covered. (65.22%)

124 existing lines in 29 files now uncovered.

1169 of 1372 relevant lines covered (85.2%)

434.92 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

61.54
/encoding/types.mbt
1
// Copyright 2024 International Digital Economy Academy
2
//
3
// Licensed under the Apache License, Version 2.0 (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
//     http://www.apache.org/licenses/LICENSE-2.0
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
///|
16
typealias Cont = (Decoder) -> Decode
17

18
///|
19
pub(all) enum Encoding {
20
  UTF8
21
  UTF16 // alias for UTF16LE
22
  UTF16LE
23
  UTF16BE
24
}
25

26
// Decoder
27

28
///|
29
priv struct Decoder {
30
  // Input bytes
31
  // Stores the input bytes that need to be decoded.
32
  // The primary data source from which characters are read and decoded.
33
  mut i : Bytes
34
  // Input position
35
  // Keeps track of the current position within the input bytes `i`.
36
  // Indicates the next byte (starting point) to read from `i` during the decoding process
37
  mut i_pos : Int
38
  // Input maximum
39
  // Indicates the index of the last byte of the input bytes `i`.
40
  // Helps bounds checking and limits how far the decoding process should go,
41
  // ensuring that decoding does not go beyond the provided input length.
42
  mut i_max : Int
43
  // Temporary bytes
44
  // Used to temporarily store bytes that are read in parts
45
  // (which might happen for multi-byte encoded characters).
46
  t : Bytes
47
  // Temporary Length
48
  // Tracks how many bytes currently reside in the temporary bytes `t`.
49
  mut t_len : Int
50
  // Temporary Need
51
  // The number of bytes still needed to complete the character code currently being processed.
52
  mut t_need : Int
53
  // Continuation
54
  //
55
  // Called with a `Decoder` state.
56
  mut k : Cont
57
}
58

59
///|
60
priv enum Decode {
61
  End
62
  Malformed(Bytes)
63
  Uchar(Char)
64
}
65

66
///|
67
fn slice(bytes : Bytes, offset : Int, length : Int) -> Bytes {
68
  let new_bytes = Bytes::new(length)
18✔
69
  new_bytes.blit(0, bytes, offset, length)
70
  new_bytes
71
}
72

73
///|
74
fn malformed(bytes : Bytes, offset : Int, length : Int) -> Decode {
75
  Malformed(slice(bytes, offset, length))
18✔
76
}
77

78
///|
79
fn malformed_pair(
80
  be : Bool,
81
  hi : Int,
82
  bytes : Bytes,
83
  offset : Int,
84
  length : Int
85
) -> Decode {
NEW
86
  let bs1 = bytes.to_unchecked_string(offset~, length~).to_bytes()
×
87
  let bs0 = b"\x00\x00"
NEW
88
  let (j0, j1) = if be { (0, 1) } else { (1, 0) }
×
89
  bs0[j0] = (hi >> 8).to_byte()
90
  bs0[j1] = hi.land(0xFF).to_byte()
91
  let bs = @buffer.new(size_hint=bs0.length() + bs1.length())
92
  bs.write_bytes(bs0)
93
  bs.write_bytes(bs1)
94
  Malformed(slice(bs.to_bytes(), 0, bs.length()))
95
}
96

97
// Chars
98

99
///|
100
type LossyChars Decoder
101

102
///|
103
pub fn iter(self : LossyChars) -> Iter[Char] {
104
  Iter::new(
14✔
105
    fn(yield_) {
106
      loop self._.decode() {
14✔
107
        Uchar(u) => {
75✔
108
          if yield_(u) == IterEnd {
NEW
109
            break IterEnd
×
110
          }
111
          continue self._.decode()
112
        }
113
        Malformed(_) => {
9✔
114
          if yield_(U_REP) == IterEnd {
NEW
115
            break IterEnd
×
116
          }
117
          continue self._.decode()
118
        }
119
        End => break IterEnd
14✔
120
      }
121
    },
122
  )
123
}
124

125
///|
126
pub fn to_string(self : LossyChars) -> String {
127
  let arr = self.iter().collect()
7✔
128
  String::from_array(arr)
129
}
130

131
///|
132
pub impl Show for LossyChars with output(self : LossyChars, logger : Logger) -> Unit {
133
  logger.write_string(self.to_string())
7✔
134
}
135

136
///|
137
type StrictChars Decoder
138

139
///|
140
pub(all) type! DecodeError Bytes
141

142
///|
143
pub impl Show for DecodeError with output(self, logger) {
144
  match self {
9✔
145
    DecodeError(err) => err.output(logger)
9✔
146
  }
147
}
148

149
///|
150
pub fn iter(self : StrictChars) -> Iter[Result[Char, DecodeError]] {
151
  Iter::new(
4✔
152
    fn(yield_) {
153
      loop self._.decode() {
4✔
154
        Uchar(u) => {
30✔
155
          if yield_(Ok(u)) == IterEnd {
NEW
156
            break IterEnd
×
157
          }
158
          continue self._.decode()
159
        }
160
        Malformed(s) => {
9✔
161
          let err = DecodeError(s)
162
          if yield_(Err(err)) == IterEnd {
NEW
163
            break IterEnd
×
164
          }
165
          continue self._.decode()
166
        }
167
        End => break IterEnd
4✔
168
      }
169
    },
170
  )
171
}
172

173
///|
174
pub fn to_string(self : StrictChars) -> String! {
NEW
175
  let arr = []
×
176
  for element in self {
177
    match element {
NEW
178
      Ok(x) => arr.push(x)
×
NEW
179
      Err(e) => raise e
×
180
    }
181
  }
182
  String::from_array(arr)
183
}
184

185
///|
186
pub impl Show for StrictChars with output(self : StrictChars, logger : Logger) -> Unit {
NEW
187
  logger.write_string(self.to_string?().to_string())
×
188
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc