Consistent overhead byte stuffing: Difference between revisions

m
→‎{{header|Wren}}: Changed to Wren S/H
m (→‎{{header|Julia}}: add variable marker, test with marker 3)
m (→‎{{header|Wren}}: Changed to Wren S/H)
 
(16 intermediate revisions by 8 users not shown)
Line 11:
;Bonus tasks:
 
::*   Decode an encoded stream, including error-check functionality.packet
**   Report an error if the final milestone exceeds the length of the end of the packet
::*   Support a non-zero marker
*   Support encoding with a non-zero marker
 
=={{Header|C}}==
 
Taken from the Wikipedia article [https://en.wikipedia.org/wiki/Consistent_Overhead_Byte_Stuffing Consistent Overhead Byte Stuffing].
 
Encoder:
Line 90 ⟶ 93:
}
</syntaxhighlight>
 
=={{header|F_Sharp|F#}}==
===The functions===
<syntaxhighlight lang="fsharp">
// Consistent overhead byte stuffing. Nigel Galloway: September 28th., 20
let rec fN g=if Seq.isEmpty g then Seq.empty else let n,_=g|>Seq.indexed|>Seq.find(fun(n,g)->n>253 || g=0uy)
seq{match n with 254->yield 255uy; yield!(g|>Seq.take 254); yield! fN(g|>Seq.skip 254)
|n->yield byte(n+1); yield!(g|>Seq.take n); yield! fN(g|>Seq.skip(n+1))}
let encode g=seq{yield! fN(seq{yield! g; yield 0uy}); yield 0uy}
let fI n=if n then [0uy] else []
let rec fG n g=seq{match Seq.head g with 0uy->() |255uy->yield! fI n; yield! g|>Seq.take 255|>Seq.skip 1; yield! fG false (g|>Seq.skip 255)
|i->yield! fI n; yield! g|>Seq.take(int i)|>Seq.skip 1; yield! fG true (g|>Seq.skip(int i))}
let decode g=fG false g
</syntaxhighlight>
 
===Tests===
<syntaxhighlight lang="fsharp">
let examples = [[0x00uy];
[0x00uy; 0x00uy];
[0x00uy; 0x11uy; 0x00uy];
[0x11uy; 0x22uy; 0x00uy; 0x33uy];
[0x11uy; 0x22uy; 0x33uy; 0x44uy];
[0x11uy; 0x00uy; 0x00uy; 0x00uy];
[0x01uy..0xfeuy];
[0x00uy..0xfeuy];
[0x01uy..0xffuy];
[0x02uy..0xffuy]@[0x00uy];
[0x03uy..0xffuy]@[0x00uy; 0x01uy]]
 
examples|>List.iter(fun g->printf "\nexample\n "
for n in g do printf "%4d" n
printfn "\nencoded"
let n=encode g
for n in n do printf "%4d" n
printf "\ndecoded\n "
for n in decode n do printf "%4d" n
printfn "")
</syntaxhighlight>
{{out}}
<pre>
example
0
encoded
1 1 0
decoded
0
 
example
0 0
encoded
1 1 1 0
decoded
0 0
 
example
0 17 0
encoded
1 2 17 1 0
decoded
0 17 0
 
example
17 34 0 51
encoded
3 17 34 2 51 0
decoded
17 34 0 51
 
example
17 34 51 68
encoded
5 17 34 51 68 0
decoded
17 34 51 68
 
example
17 0 0 0
encoded
2 17 1 1 1 0
decoded
17 0 0 0
 
example
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 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254
encoded
255 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 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 1 0
decoded
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 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254
 
example
0 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 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254
encoded
1 255 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 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 1 0
decoded
0 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 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254
 
example
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 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255
encoded
255 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 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 2 255 0
decoded
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 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255
 
example
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 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 0
encoded
255 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 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 1 1 0
decoded
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 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 0
 
example
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 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 0 1
encoded
254 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 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 2 1 0
decoded
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 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 0 1
</pre>
 
=={{Header|Insitux}}==
 
<syntaxhighlight lang="insitux">
(function COBS unencoded _encoded
(let chunk (take-until [0] unencoded)
length (len chunk)
encoded (append (first 254 chunk) (or %1_encoded []))
more? (< length (len unencoded)))
(ifwhen (or (< 254 length) (and (= length 254) more?) (> length 254)more?)
(recur (skip (min 254 (inc length)) unencoded) encoded))
(append 0 (flat-map @(.. vec (inc (len %))) encoded)))
(if more?
(recur (skip (inc length) unencoded) encoded)
(append 0 (flat-map @(.. vec (inc (len %))) encoded)))))
</syntaxhighlight>
 
Line 129 ⟶ 247:
<syntaxhighlight lang="julia">module COBSPackets
 
export cobs_encode, cobs_decode, cencode, cdecode, crencode, crdecode, setCOBSerrormode
export COBSencode, COBSdecode
 
const _errormode = [:IGNORE]
 
"""
setCOBSerrormode(mode::Symbol)
 
Set decoding error reporting mode.
Default is :IGNORE. :WARN prints to stderr, :THROW will cause error exit.
"""
setCOBSerrormode(mode::Symbol) = begin _errormode[begin] = mode end
COBSencode(data)
 
""" reporting for decoding errors (a marker byte in the wrong location) """
Return result of encoding `inputdata` into COBS packet format.
function _err(marker, position)
if _errormode[begin] == :WARN
@warn("packet error: found $marker at $position")
elseif _errormode[begin] == :THROW
error("packet error: found $marker at $position")
end
end
 
"""
cobs_encode(data; reduced = false, marker = 0x00)
 
Return result of encoding `inputdata` into COBS or COBS/R packet format.
If `reduced` is true will use the COBS/R protocol, if false the COBS protocol.
The `marker` defaults to zero but may be any byte from 0 to 254.
See also: COBS: www.stuartcheshire.org/papers/COBSforToN.pdf
COBS/R: pythonhosted.org/cobs/cobsr-intro.html
"""
function COBSencodecobs_encode(inputdata; reduced = false, marker = 0x00)
output = [0xff]
codeindex, lastindex, code = 1, 1, 1
addlastcode = true
for byte in inputdata
if byte != marker0x00
push!(output, byte)
code += 1
end
addlastcode = true
if byte == marker0x00 || code == 255
code == 255 && (addlastcode = false)
output[codeindex] = code
Line 152 ⟶ 293:
push!(output, 0xff)
codeindex = length(output)
byte == 0x00 && (lastindex = codeindex)
end
end
if addlastcode
output[codeindex] = code
push!(output, marker0x00)
else
output[codeindex] = marker0x00
end
return# Reduce size output of by 1 char if can
if reduced && lastindex > 1 && output[end-1] + lastindex > length(output)
output[lastindex] = output[end-1]
output[end-1] = 0x00
pop!(output)
end
return marker == 0x00 ? output : UInt8.(output .⊻ marker)
end
 
""" short name for COBS encoding """
cencode(data; marker = 0x00) = cobs_encode(data, marker = marker, reduced = false)
 
""" short name for COBS/R encoding """
crencode(data; marker = 0x00) = cobs_encode(data, marker = marker, reduced = true)
 
"""
COBSdecodecobs_decode(buffer; reduced = false, marker = 0x00)
 
Return result of decoding `bufferinputdata` from COBS encodedor COBS/R packet format.
If `reduced` is true will use the COBS/R protocol, if false the COBS protocol.
The `marker` defaults to zero but may be any byte from 0 to 254.
See also: COBS: www.stuartcheshire.org/papers/COBSforToN.pdf
COBS/R: pythonhosted.org/cobs/cobsr-intro.html
"""
function COBSdecodecobs_decode(buffer::AbstractVector; reduced = false, marker = 0x00)
buffer[end] != marker && _err(buffer[end], "end")
buf = marker == 0 ? buffer : UInt8.(copy(buffer) .⊻ marker)
decoded = UInt8[]
bdx, len = 1, length(bufferbuf)
lpos, lchar = 1, 0
while bdx < len
code = bufferbuf[bdx]
code == 0x00 && bdx != 1 && _err(marker, bdx)
lpos, lchar = bdx, code
bdx += 1
for i_ in= 1:code-1
push!(decoded,byte buffer= buf[bdx])
byte == 0x00 && bdx < len && _err(marker, bdx)
push!(decoded, byte)
bdx += 1
if bdx >= len && break
!reduced && _err("index", "\b\b\bpast end of packet")
break
end
end
code < 0xff && bdx < len && push!(decoded, marker0x00)
end
# Restore from reduced format if present
reduced && lchar != 0x00 && lchar + lpos > len && (decoded[end] = lchar)
return decoded
end
 
""" short name for COBS decoding """
cdecode(data; marker = 0x00) = cobs_decode(data, marker = marker, reduced = false)
 
""" short name for COBS/R decoding """
crdecode(data; marker = 0x00) = cobs_decode(data, marker = marker, reduced = true)
 
end # module
Line 208 ⟶ 384:
 
for t in tests
println(ab(t), " -> ", ab(COBSencodecencode(t, marker = 3)), " -> ", ab(COBSdecode(COBSencode(t, 3), 3)))
ab(cdecode(cencode(t, marker = 3), marker = 3)))
end
 
using Test # module unit tests for error handling, etc.
 
for t in tests
setCOBSerrormode(:THROW)
@test t == crdecode(crencode(t))
@test t == crdecode(crencode(t, marker = 3), marker = 3)
@test t == cdecode(cencode(t, marker = 0xfe), marker = 0xfe)
if length(t) > 14
for m in 0:255
t2 = cencode(t, marker = m)
t2[3:10] .= m # introduce error
setCOBSerrormode(:WARN)
@test_warn "error" length(t2) > 15 && t != cdecode(t2, marker = m)
setCOBSerrormode(:THROW)
@test_throws "error" t != cdecode(t2, marker = m)
setCOBSerrormode(:IGNORE)
@test_nowarn t != cdecode(t2, marker = m)
end
end
@test t == crdecode(crencode(t))
@test t == crdecode(crencode(t, marker = 3), marker = 3)
@test t == crdecode(crencode(t, marker = 0xfe), marker = 0xfe)
setCOBSerrormode(:IGNORE)
if length(t) > 10
for m in 1:255 # marker type change
@test t != cdecode(cencode(t, marker = m), marker = 0)
@test t != crdecode(crencode(t, marker = m), marker = 0)
end
end
setCOBSerrormode(:WARN)
if !isempty(setdiff(cencode(t), crencode(t)))
@test_warn "past" t != cdecode(crencode(t))
end
end
</syntaxhighlight>{{out}}
<pre>
00 -> 0102 0102 0003 -> 00
00 00 -> 0102 0102 0102 0003 -> 00 00
00 11 00 -> 01 02 11 01 0012 02 03 -> 00 11 00
11 22 00 33 -> 0300 1112 2221 0201 3330 0003 -> 11 22 00 33
11 22 33 44 -> 0506 1112 2221 3330 4447 0003 -> 11 22 33 44
11 00 00 00 -> 0201 1112 0102 0102 0102 0003 -> 11 00 00 00
01 02 03 04 ... fb fc fd fe -> ff 01fc 02 0301 00 ... fc fdff fe 00fd 03 -> 01 02 03 04 ... fb fc fd fe
00 01 02 03 ... fb fc fd fe -> 0102 ff 01fc 02 01 ... fc fdff fe 00fd 03 -> 00 01 02 03 ... fb fc fd fe
01 02 03 04 ... fc fd fe ff -> ff 01fc 02 0301 00 ... fefd 0201 fffc 0003 -> 01 02 03 04 ... fc fd fe ff
02 03 04 05 ... fd fe ff 00 -> fffc 0201 0300 0407 ... fffc 0102 0102 0003 -> 02 03 04 05 ... fd fe ff 00
03 04 05 06 ... fe ff 00 01 -> fefd 0300 0407 0506 ... ff 02fc 01 0002 03 -> 03 04 05 06 ... fe ff 00 01
</pre>
 
=={{header|Perl}}==
<syntaxhighlight lang="perl">#!/usr/bin/perl
 
use strict; # https://rosettacode.org/wiki/Consistent_overhead_byte_stuffing
use warnings;
 
my @data = map { pack 'H*', tr/ //dr } split /\n/, <<END;
00
00 00
00 11 00
11 22 00 33
11 22 33 44
11 00 00 00
00 00 00 00 00 00
33 33 33 33 33 33 33
END
push @data, ( " " x $_ ) for 1269 .. 1272;
 
sub showbytes
{
my @bytes = map /../g, unpack 'H*', pop;
print "@_: ",
"@bytes\n" =~ s!(\w\w)\K(( \1){7,})! 'x' . (1 + length($2) / 3) !ger;
}
 
my $marker = "\0"; # the byte that is eliminated from string
 
sub encode
{
return join '',
(map chr(1 + length) . $_, # prepend length
map /.{1,254}|^\z/gs, # break up long sections
split /\Q$marker/, shift, -1), $marker;
}
 
sub decode
{
(local $_, my $keep, my $answer) = (shift, 0, '');
while( /\G[^\Q$marker\E]/g ) # advance over count byte
{
my $len = -1 + ord $&; # length of data block
$answer .= $marker x $keep . (/\G[^\Q$marker\E]{$len}/g, $&);
$keep = $len < 254; # was split on marker, not size
}
return $answer;
}
 
for my $original ( @data )
{
showbytes 'original', $original;
showbytes ' encoded', my $answer = encode $original;
showbytes ' decoded', my $decoded = decode $answer;
$original eq $decoded or die "MISMATCH";
print "\n";
}</syntaxhighlight>
{{out}}
<pre>
original: 00
encoded: 01 01 00
decoded: 00
 
original: 00 00
encoded: 01 01 01 00
decoded: 00 00
 
original: 00 11 00
encoded: 01 02 11 01 00
decoded: 00 11 00
 
original: 11 22 00 33
encoded: 03 11 22 02 33 00
decoded: 11 22 00 33
 
original: 11 22 33 44
encoded: 05 11 22 33 44 00
decoded: 11 22 33 44
 
original: 11 00 00 00
encoded: 02 11 01 01 01 00
decoded: 11 00 00 00
 
original: 00 00 00 00 00 00
encoded: 01 01 01 01 01 01 01 00
decoded: 00 00 00 00 00 00
 
original: 33 33 33 33 33 33 33
encoded: 08 33 33 33 33 33 33 33 00
decoded: 33 33 33 33 33 33 33
 
original: 20x1269
encoded: ff 20x254 ff 20x254 ff 20x254 ff 20x254 fe 20x253 00
decoded: 20x1269
 
original: 20x1270
encoded: ff 20x254 ff 20x254 ff 20x254 ff 20x254 ff 20x254 00
decoded: 20x1270
 
original: 20x1271
encoded: ff 20x254 ff 20x254 ff 20x254 ff 20x254 ff 20x254 02 20 00
decoded: 20x1271
 
original: 20x1272
encoded: ff 20x254 ff 20x254 ff 20x254 ff 20x254 ff 20x254 03 20 20 00
decoded: 20x1272
 
</pre>
 
=={{header|Phix}}==
{{trans|Wren}}
<!--<syntaxhighlight lang="phix">(phixonline)-->
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">cobs_encode</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequencestring</span> <span style="color: #000000;">data</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">integer</span> <span style="color: #000000;">delim</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">sequencestring</span> <span style="color: #000000;">bufferenc</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF008000;">{-</span><span style="color: #000000;?">1</span><span style="color: #0000FF;">}</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">cdxins</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">code</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">addlastaddLastCode</span> <span style="color: #0000FF;">=</span> <span style="color: #004600;">true</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">b</span> <span style="color: #008080;">in</span> <span style="color: #000000;">data</span> <span style="color: #008080;">do</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">b</span><span style="color: #0000FF;">!=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">bufferenc</span> <span style="color: #0000FF;">&=</span> <span style="color: #000000;">b</span>
<span style="color: #000000;">code</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #000000;">addlastaddLastCode</span> <span style="color: #0000FF;">=</span> <span style="color: #004600;">true</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">b</span><span style="color: #0000FF;">==</span><span style="color: #000000;">0</span> <span style="color: #008080;">or</span> <span style="color: #000000;">code</span> <span style="color: #0000FF;">==</span> <span style="color: #000000;">0xFF255</span> <span style="color: #008080;">then</span>
<span style="color: #000000008080;">addlastif</span> <span style="color: #000000;">code</span><span style="color: #0000FF;">==</span><span style="color: #000000;">255</span> <span style="color: #008080;">then</span> <span style="color: #000000;">codeaddLastCode</span> <span style="color: #0000FF;">!=</span> <span style="color: #000000004600;">false</span> <span style="color: #008080;">end</span> <span style="color: #008080;">0xFFif</span>
<span style="color: #000000;">bufferenc</span><span style="color: #0000FF;">[</span><span style="color: #000000;">cdxins</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">code</span>
<span style="color: #000000;">code</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span>
<span style="color: #000000;">bufferenc</span> <span style="color: #0000FF;">&=</span> <span style="color: #0000FF;">-</span><span style="color: #000000008000;">1'?'</span>
<span style="color: #000000;">cdxins</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">bufferenc</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">addLastCode</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">buffer</span><span style="color: #0000FF;">[</span><span style="color: #000000;">cdx</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">iff</span><span style="color: #0000FF;">(</span><span style="color: #000000;">addlast</span><span style="color: #0000FF;">?</span><span style="color: #000000;">code</span><span style="color: #0000FF;">:</span><span style="color: #000000;">0</span><span style="color: #0000FF;">)</span>
<span style="color: #008080000000;">ifenc</span><span style="color: #0000FF;">[</span><span style="color: #000000;">addlastins</span><span style="color: #0000FF;">]</span> <span style="color: #0080800000FF;">=</span> <span style="color: #000000;">thencode</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">delim</span><span style="color: #0000FF;">!=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span> <span style="color: #000000;">enc</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">sq_xor_bits</span><span style="color: #0000FF;">(</span><span style="color: #000000;">enc</span><span style="color: #0000FF;">,</span><span style="color: #000000;">delim</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #000000;">buffer</span> <span style="color: #0000FF;">&=</span> <span style="color: #000000;">0</span>
<span style="color: #000000;">enc</span> <span style="color: #0000FF;">&=</span> <span style="color: #000000;">delim</span>
<span style="color: #008080;">else</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">delim</span><span style="color: #0000FF;">!=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span> <span style="color: #000000;">enc</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">sq_xor_bits</span><span style="color: #0000FF;">(</span><span style="color: #000000;">enc</span><span style="color: #0000FF;">,</span><span style="color: #000000;">delim</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #000000;">enc</span><span style="color: #0000FF;">[</span><span style="color: #000000;">ins</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">delim</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">bufferenc</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">cobs_decode</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequencestring</span> <span style="color: #000000;">bufferenc</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">integer</span> <span style="color: #000000;">delim</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span><span style="color: #0000FF;">)</span>
<span style="color: #0040807060A8;">sequenceassert</span><span style="color: #0000FF;">(</span><span style="color: #000000;">dataenc</span> <span style="color: #0000FF;">[$]==</span><span style="color: #000000;">delim</span><span style="color: #0000FF;">{})</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">bdxenc</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1enc</span><span style="color: #0000FF;">,[</span> <span style="color: #000000;">l</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">length1</span><span style="color: #0000FF;">(..-</span><span style="color: #000000;">buffer2</span><span style="color: #0000FF;">)]</span>
<span style="color: #008080004080;">whileinteger</span> <span style="color: #000000;">bdxl</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">lenc</span><span style="color: #0000FF;">),</span> <span style="color: #008080000000;">code</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">255</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">block</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">do0</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">delim</span> <span style="color: #004080008080;">integerthen</span> <span style="color: #000000;">codeenc</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">sq_xor_bits</span><span style="color: #0000FF;">(</span><span style="color: #000000;">bufferenc</span><span style="color: #0000FF;">[,</span><span style="color: #000000;">bdxdelim</span><span style="color: #0000FF;">])</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #004080;">string</span> <span style="color: #000000;">bdxdata</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000008000;">1""</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">code</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1l</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">datab</span> <span style="color: #0000FF;">&=</span> <span style="color: #000000;">bufferenc</span><span style="color: #0000FF;">[</span><span style="color: #000000;">bdxi</span><span style="color: #0000FF;">]</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">bdxblock</span> <span style="color: #0000FF;">+!=</span> <span style="color: #000000;">10</span> <span style="color: #008080;">then</span>
<span style="color: #008080000000;">enddata</span> <span style="color: #0000FF;">&=</span> <span style="color: #008080000000;">forb</span>
<span style="color: #008080;">else</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">code</span><span style="color: #0000FF;"><</span><span style="color: #000000;">0xFF</span> <span style="color: #008080;">and</span> <span style="color: #000000;">bdx</span><span style="color: #0000FF;"><</span><span style="color: #000000;">l</span> <span style="color: #008080;">then</span>
<span style="color: #7060A8;">assert</span><span style="color: #0000FF;">((</span><span style="color: #000000;">datai</span><span style="color: #0000FF;">+</span><span style="color: #000000;">b</span><span style="color: #0000FF;">&-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)<=</span><span style="color: #000000;">0l</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"marker pointing beyond the end of packet"</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">code</span><span style="color: #0000FF;">!=</span><span style="color: #000000;">255</span> <span style="color: #008080;">then</span> <span style="color: #000000;">data</span> <span style="color: #0000FF;">&=</span> <span style="color: #000000;">0</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #000000;">code</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">b</span>
<span style="color: #000000;">block</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">code</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">code</span><span style="color: #0000FF;">==</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span> <span style="color: #008080;">exit</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080000000;">endblock</span> <span style="color: #0000FF;">-=</span> <span style="color: #008080000000;">while1</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">data</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">constantfunction</span> <span style="color: #000000;">tests</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{{{</span><span style="color: #000000;">0x00</span><span style="color: #0000FF;">},</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">0x01</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">0x01</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">0x00string00FF</span><span style="color: #0000FF;">}},()</span>
<span style="color: #0000FF004080;">{{</span><span style="color: #000000;">0x00</span><span style="color: #0000FF;">,string</span> <span style="color: #000000;">0x00</span><span style="color: #0000FF;">},res</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">0x01</span><span style="color: #0000FF;">,</span> <span style="color: #000000008000;">0x01</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">0x01</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">0x00</span><span style="color: #0000FF;">}},</span>
<span style="color: #0000FF008080;">{{for</span> <span style="color: #000000;">0x00ch</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">0x11</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">0x00</span> <span style="color: #0000FF008080;">},to</span> <span style="color: #0000FF000000;">{0xFF</span><span style="color: #000000;">0x01</span><span style="color: #0000FF008080;">,do</span> <span style="color: #000000;">0x02res</span> <span style="color: #0000FF;">,&=</span> <span style="color: #000000;">0x11</span><span style="color: #0000FF;">,ch</span> <span style="color: #000000008080;">0x01</span><span style="color: #0000FF;">,end</span> <span style="color: #000000;">0x00</span><span style="color: #0000FF008080;">}},for</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">res</span>
<span style="color: #0000FF;">{{</span><span style="color: #000000;">0x11</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">0x22</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">0x00</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">0x33</span><span style="color: #0000FF;">},</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">0x03</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">0x11</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">0x22</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">0x02</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">0x33</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">0x00</span><span style="color: #0000FF;">}},</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #0000FF;">{{</span><span style="color: #000000;">0x11</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">0x22</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">0x33</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">0x44</span><span style="color: #0000FF;">},</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">0x05</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">0x11</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">0x22</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">0x33</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">0x44</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">0x00</span><span style="color: #0000FF;">}},</span>
<span style="color: #0000FF;">{{</span><span style="color: #000000;">0x11</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">0x00</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">0x00</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">0x00</span><span style="color: #0000FF;">},</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">0x02</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">0x11</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">0x01</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">0x01</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">0x01</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">0x00</span><span style="color: #0000FF;">}},</span>
<span style="color: #0000FF008080;">{constant</span><span style="color: #7060A8;">tagset</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0xFEt00toFF</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0x01</span><span style="color: #0000FF;">),</span> <span style="color: #7060A8;">flatten</span><span style="color: #0000FF;">({</span><span style="color: #000000;">0xFF</span><span style="color: #0000FF;">,</span> <span style="color: #7060A8;">tagsetstring00FF</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0xFE</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0x01</span><span style="color: #0000FF;">),</span> <span style="color: #000000;">0x00</span><span style="color: #0000FF;">})},</span>
<span style="color: #0000FF;">{</span><span style="color: #7060A8;">tagset</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0xFEt00FE</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0x00</span><span style="color: #0000FF;">),</span> <span style="color: #7060A8;">flatten</span><span style="color: #0000FF;">({</span><span style="color: #000000;">0x01t00toFF</span><span style="color: #0000FF;">,[</span> <span style="color: #000000;">0xFF1</span><span style="color: #0000FF;">,..-</span> <span style="color: #7060A8;">tagset</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0xFE</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0x01</span><span style="color: #0000FF;">),</span> <span style="color: #000000;">0x002</span><span style="color: #0000FF;">})}],</span>
<span style="color: #0000FF;">{</span><span style="color: #7060A8;">tagset</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0xFFt01FE</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0x01</span><span style="color: #0000FF;">),</span> <span style="color: #7060A8;">flatten</span><span style="color: #0000FF;">({</span><span style="color: #000000;">0xFFt00toFF</span><span style="color: #0000FF;">,</span> <span style="color: #7060A8;">tagset</span><span style="color: #0000FF;">([</span><span style="color: #000000;">0xFE2</span><span style="color: #0000FF;">,..-</span><span style="color: #000000;">0x01</span><span style="color: #0000FF;">),</span> <span style="color: #000000;">0x02</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">0xFF</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">0x002</span><span style="color: #0000FF;">})}],</span>
<span style="color: #0000FF;">{</span><span style="color: #7060A8;">tagset</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0xFFt01FF</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0x02</span><span style="color: #0000FF;">)</span> <span style="color: #0000FF;">&</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">0x00t00toFF</span><span style="color: #0000FF;">},</span> <span style="color: #7060A8;">flatten</span><span style="color: #0000FF;">({[</span><span style="color: #000000;">0xFF2</span><span style="color: #0000FF;">,..-</span> <span style="color: #7060A8;">tagset</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0xFF</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0x02</span><span style="color: #0000FF;">),</span> <span style="color: #000000;">0x01</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">0x01</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">0x001</span><span style="color: #0000FF;">})}],</span>
<span style="color: #0000FF;">{</span><span style="color: #7060A8;">tagset</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0xFFt02FF</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0x03</span><span style="color: #0000FF;">)</span> <span style="color: #0000FF;">&</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">0x00t00toFF</span><span style="color: #0000FF;">,[</span> <span style="color: #000000;">0x013</span><span style="color: #0000FF;">},</span> <span style="color: #7060A8;">flatten</span><span style="color: #0000FF;">({..-</span><span style="color: #000000;">0xFE1</span><span style="color: #0000FF;">],</span> <span style="color: #7060A8;">tagset</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0xFF</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0x03</span><span style="color: #0000FF;">),</span> <span style="color: #000000;">0x02</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">0x01</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">0x00</span><span style="color: #0000FF;">})}}</span>
<span style="color: #008080000000;">fort03FF</span> <span style="color: #0000000000FF;">t=</span> <span style="color: #008080000000;">int00toFF</span><span style="color: #0000FF;">[</span><span style="color: #000000;">tests4</span><span style="color: #0000FF;">..-</span><span style="color: #000000;">1</span><span style="color: #0080800000FF;">do],</span>
<span style="color: #004080;">sequence</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">origtests</span> <span style="color: #0000FF;">,=</span> <span style="color: #0000000000FF;">expected{{</span><span style="color: #0000FF008000;">}x"00"</span> <span style="color: #0000FF;">=,</span> <span style="color: #000000008000;">tx"010100"</span><span style="color: #0000FF;">},</span>
<span style="color: #000000;">actual</span> <span style="color: #0000FF;">={</span> <span style="color: #000000008000;">cobs_encodex"0000"</span><span style="color: #0000FF;">(,</span> <span style="color: #000000008000;">origx"01010100"</span><span style="color: #0000FF;">)},</span>
<span style="color: #000000;">decoded</span> <span style="color: #0000FF;">={</span> <span style="color: #000000008000;">cobs_decodex"001100"</span><span style="color: #0000FF;">(,</span> <span style="color: #000000008000;">actualx"0102110100"</span><span style="color: #0000FF;">)},</span>
<span style="color: #004080;">string</span> <span style="color: #000000;">ostr</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">iff</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">orig</span><span style="color: #0000FF;">)<</span><span style="color: #000000;">5</span><span style="color: #0000FF;">?</span><span style="color: #7060A8;">join</span><span style="color: #0000FF;">(</span><span style="color: #000000;">orig</span><span style="color: #0000FF;">,{</span><span style="color: #008000;">x" 11220033"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">fmt</span><span style="color: #0000FF;">:=</span><span style="color: #008000;">x"%02x031122023300"</span><span style="color: #0000FF;">)},</span>
<span style="color: #0000FF;">:</span><span style="color: #7060A8;">join</span><span style="color: #0000FF;">(</span><span style="color: #000000;">orig</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">..</span><span style="color: #000000;">3</span><span style="color: #0000FF;">],</span><span style="color: #000000;">fmt</span><span style="color: #0000FF;">:={</span><span style="color: #008000;">x"%02x11223344"</span><span style="color: #0000FF;">)&</span><span style="color: #008000;">" ... "</span><span style="color: #0000FF;">&</span><span style="color: #7060A8;">join</span><span style="color: #0000FF;">(</span><span style="color: #000000;">orig</span><span style="color: #0000FF;">[</span><span style="color: #000000;">253</span><span style="color: #0000FF;">..$],</span><span style="color: #000000;">fmt</span><span style="color: #0000FF;">:=</span><span style="color: #008000;">x"%02x051122334400"</span><span style="color: #0000FF;">))},</span>
<span style="color: #000000;">astr</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">iff</span><span style="color: #0000FF;">({</span><span style="color: #7060A8008000;">length</span><span style=x"color: #0000FF;11000000">(</span><span style="color: #000000;">actual</span><span style="color: #0000FF;">)<</span><span style="color: #000000;">7</span><span style="color: #0000FF;">?</span><span style="color: #7060A8;">join</span><span style="color: #0000FF;">(</span><span style="color: #000000;">actual</span><span style="color: #0000FF;">,</span><span style="color: #000000;">fmt</span><span style="color: #0000FF;">:=</span><span style="color: #008000;">x"%02x021101010100"</span><span style="color: #0000FF;">)},</span>
<span style="color: #0000FF;">:</span><span style="color: #7060A8;">join</span><span style="color: #0000FF;">({</span><span style="color: #000000;">actualt01FE</span><span style="color: #0000FF;">[,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">..</span><span style="color: #000000;">40xFF</span><span style="color: #0000FF;">],</span><span style="color: #000000;">fmt</span><span style="color: #0000FF;">:=&</span><span style="color: #008000;">"%02x"</span><span style="color: #0000FF000000;">)&t01FE</span><span style="color: #008000;">" ... "</span><span style="color: #0000FF;">&</span><span style="color: #7060A8;">join</span><span style="color: #0000FF;">(</span><span style="color: #000000;">actual</span><span style="color: #0000FF;">[</span><span style="color: #000000;">254</span><span style="color: #0000FF;">..$],</span><span style="color: #000000;">fmt</span><span style="color: #0000FF;">:=</span><span style="color: #008000;">"%02x"0x00</span><span style="color: #0000FF;">))},</span>
<span style="color: #000000;">eOK</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">iff</span><span style="color: #0000FF;">({</span><span style="color: #000000;">actualt00FE</span><span style="color: #0000FF;">==,</span> <span style="color: #000000008000;">expectedx"01FF"</span> <span style="color: #0000FF;">?&</span> <span style="color: #008000000000;">"OK"t01FE</span> <span style="color: #0000FF;">:&</span> <span style="color: #008000000000;">"***???***"0x00</span><span style="color: #0000FF;">)},</span>
<span style="color: #000000;">dOK</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">iff</span><span style="color: #0000FF;">({</span><span style="color: #000000;">decodedt01FF</span><span style="color: #0000FF;">==,</span> <span style="color: #000000;">orig0xFF</span> <span style="color: #0000FF;">?&</span> <span style="color: #008000000000;">"OK"t01FE</span> <span style="color: #0000FF;">:&</span> <span style="color: #008000;">x"***???***02FF00"</span><span style="color: #0000FF;">)},</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span> <span style="color: #0000FF;">,{</span><span style="color: #008000000000;">"%-23s -&gt; %-33s encode:%s, decode: %s\n"t02FF</span> <span style="color: #0000FF;">,{&</span> <span style="color: #000000;">ostr0x00</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">astr0xFF</span> <span style="color: #0000FF;">,&</span> <span style="color: #000000;">eOKt02FF</span> <span style="color: #0000FF;">,&</span> <span style="color: #000000008000;">dOKx"010100"</span><span style="color: #0000FF;">}),</span>
<span style="color: #0000FF;">{</span><span style="color: #000000;">t03FF</span> <span style="color: #0000FF;">&</span> <span style="color: #008000;">x"0001"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">0xFE</span> <span style="color: #0000FF;">&</span> <span style="color: #000000;">t03FF</span> <span style="color: #0000FF;">&</span> <span style="color: #008000;">x"020100"</span><span style="color: #0000FF;">}}</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">ab</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">s</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">integer</span> <span style="color: #000000;">m</span><span style="color: #0000FF;">,</span><span style="color: #000000;">f</span><span style="color: #0000FF;">,</span><span style="color: #000000;">l</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">s</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">iff</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">s</span><span style="color: #0000FF;">)<</span><span style="color: #000000;">m</span><span style="color: #0000FF;">?</span><span style="color: #7060A8;">join</span><span style="color: #0000FF;">(</span><span style="color: #000000;">s</span><span style="color: #0000FF;">,</span><span style="color: #000000;">fmt</span><span style="color: #0000FF;">:=</span><span style="color: #008000;">"%02x"</span><span style="color: #0000FF;">)</span>
<span style="color: #0000FF;">:</span><span style="color: #7060A8;">join</span><span style="color: #0000FF;">(</span><span style="color: #000000;">s</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">..</span><span style="color: #000000;">f</span><span style="color: #0000FF;">],</span><span style="color: #000000;">fmt</span><span style="color: #0000FF;">:=</span><span style="color: #008000;">"%02x"</span><span style="color: #0000FF;">)</span>
<span style="color: #0000FF;">&</span> <span style="color: #008000;">" ... "</span> <span style="color: #0000FF;">&</span> <span style="color: #7060A8;">join</span><span style="color: #0000FF;">(</span><span style="color: #000000;">s</span><span style="color: #0000FF;">[</span><span style="color: #000000;">l</span><span style="color: #0000FF;">..$],</span><span style="color: #000000;">fmt</span><span style="color: #0000FF;">:=</span><span style="color: #008000;">"%02x"</span><span style="color: #0000FF;">))</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">s</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">delim</span> <span style="color: #008080;">in</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">0x00</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">0x02</span><span style="color: #0000FF;">}</span> <span style="color: #008080;">do</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%nUsing delim 0x%02x:\n"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">delim</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">t</span> <span style="color: #008080;">in</span> <span style="color: #000000;">tests</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">sequence</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">orig</span><span style="color: #0000FF;">,</span><span style="color: #000000;">expected</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">t</span><span style="color: #0000FF;">,</span>
<span style="color: #000000;">actual</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">cobs_encode</span><span style="color: #0000FF;">(</span><span style="color: #000000;">orig</span><span style="color: #0000FF;">,</span><span style="color: #000000;">delim</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">decoded</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">cobs_decode</span><span style="color: #0000FF;">(</span><span style="color: #000000;">actual</span><span style="color: #0000FF;">,</span><span style="color: #000000;">delim</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">delim</span> <span style="color: #008080;">then</span> <span style="color: #000000;">expected</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">sq_xor_bits</span><span style="color: #0000FF;">(</span><span style="color: #000000;">expected</span><span style="color: #0000FF;">,</span><span style="color: #000000;">delim</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #004080;">bool</span> <span style="color: #000000;">eOK</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">actual</span><span style="color: #0000FF;">==</span><span style="color: #000000;">expected</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">dOK</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">decoded</span><span style="color: #0000FF;">==</span><span style="color: #000000;">orig</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%-23s -&gt; %-33s encode:%t, decode:%t\n"</span><span style="color: #0000FF;">,</span>
<span style="color: #0000FF;">{</span><span style="color: #000000;">ab</span><span style="color: #0000FF;">(</span><span style="color: #000000;">orig</span><span style="color: #0000FF;">,</span><span style="color: #000000;">5</span><span style="color: #0000FF;">,</span><span style="color: #000000;">3</span><span style="color: #0000FF;">,</span><span style="color: #000000;">253</span><span style="color: #0000FF;">),</span><span style="color: #000000;">ab</span><span style="color: #0000FF;">(</span><span style="color: #000000;">actual</span><span style="color: #0000FF;">,</span><span style="color: #000000;">7</span><span style="color: #0000FF;">,</span><span style="color: #000000;">4</span><span style="color: #0000FF;">,</span><span style="color: #000000;">254</span><span style="color: #0000FF;">),</span><span style="color: #000000;">eOK</span><span style="color: #0000FF;">,</span><span style="color: #000000;">dOK</span><span style="color: #0000FF;">})</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<!--</syntaxhighlight>-->
{{out}}
<pre>
Using delim 0x00:
00 -> 01 01 00 encode:OK, decode: OK
00 00 -> 01 01 01 00 encode:OKtrue, decode: OKtrue
00 11 00 -> 01 02 1101 01 00 encode:OKtrue, decode: OKtrue
1100 2211 00 33 -> 0301 02 11 2201 00 02 33 00 encode:OKtrue, decode: OKtrue
11 22 00 33 44 -> 0503 11 22 3302 4433 00 encode:OKtrue, decode: OKtrue
11 0022 0033 0044 -> 0205 11 0122 0133 0144 00 encode:OKtrue, decode: OKtrue
0111 00 00 00 02 03 ... FD FE -> FF02 11 01 0201 01 00 03 ... FD FE 00 encode:OKtrue, decode: OKtrue
00 01 02 03 ... FC FD FE -> 01 FF 01 02 03 ... FC FD FE 00 encode:OKtrue, decode: OKtrue
00 01 02 03 ... FC FD FE FF -> 01 FF 01 02 03 ... FC FD FE 0200 FF 00 encode:OKtrue, decode: OKtrue
01 02 03 04 ... FD FE FF 00 -> FF 01 02 03 04 ... FD FE 02 FF 01 01 00 encode:OKtrue, decode: OKtrue
02 03 04 05 ... FE FF 00 01 -> FEFF 02 03 04 05 ... FE FF 0201 01 00 encode:OKtrue, decode: OKtrue
03 04 05 ... FF 00 01 -> FE 03 04 05 ... FF 02 01 00 encode:true, decode:true
 
Using delim 0x02:
00 -> 03 03 02 encode:true, decode:true
00 00 -> 03 03 03 02 encode:true, decode:true
00 11 00 -> 03 00 13 03 02 encode:true, decode:true
11 22 00 33 -> 01 13 20 00 31 02 encode:true, decode:true
11 22 33 44 -> 07 13 20 31 46 02 encode:true, decode:true
11 00 00 00 -> 00 13 03 03 03 02 encode:true, decode:true
01 02 03 ... FD FE -> FD 03 00 01 ... FF FC 02 encode:true, decode:true
00 01 02 ... FC FD FE -> 03 FD 03 00 ... FE FF FC 02 encode:true, decode:true
01 02 03 ... FD FE FF -> FD 03 00 01 ... FF FC 00 FD 02 encode:true, decode:true
02 03 04 ... FE FF 00 -> FD 00 01 06 ... FC FD 03 03 02 encode:true, decode:true
03 04 05 ... FF 00 01 -> FC 01 06 07 ... FD 00 03 02 encode:true, decode:true
</pre>
 
=={{header|Python}}==
 
Based on several existing solutions. Assumes a zero byte packet delimiter.
 
<syntaxhighlight lang="python">
"""Consistent overhead byte stuffing. Requires Python >= 3.10."""
 
from itertools import islice
 
 
def cob_encode(data: bytes | bytearray) -> bytearray:
buffer = bytearray([0])
code_index = 0
code = 1
final_code = True
 
for byte in data:
final_code = True
if byte:
buffer.append(byte)
code += 1
 
if not byte or code == 0xFF:
if code == 0xFF:
final_code = False
 
buffer[code_index] = code
code = 1
buffer.append(0)
code_index = len(buffer) - 1
 
if final_code:
assert not buffer[code_index]
buffer[code_index] = code
 
if buffer[-1]:
buffer.append(0)
 
return buffer
 
 
def cob_decode(encoded: bytes | bytearray) -> bytearray:
buffer = bytearray()
code = 0xFF
block = 0
 
for byte in islice(encoded, len(encoded) - 1):
if block:
buffer.append(byte)
else:
if code != 0xFF:
buffer.append(0)
 
block = code = byte
 
if not code:
break
 
block -= 1
 
return buffer
 
 
EXAMPLES = [
(bytearray.fromhex("00"), bytearray.fromhex("01 01 00")),
(bytearray.fromhex("00 00"), bytearray.fromhex("01 01 01 00")),
(bytearray.fromhex("00 11 00"), bytearray.fromhex("01 02 11 01 00")),
(bytearray.fromhex("11 22 00 33"), bytearray.fromhex("03 11 22 02 33 00")),
(bytearray.fromhex("11 22 33 44"), bytearray.fromhex("05 11 22 33 44 00")),
(bytearray.fromhex("11 00 00 00"), bytearray.fromhex("02 11 01 01 01 00")),
(
bytearray(range(0x01, 0xFE + 1)),
bytearray([0xFF, *range(1, 0xFE + 1), 0x00]),
),
(
bytearray(range(0x00, 0xFE + 1)),
bytearray([0x01, 0xFF, *range(1, 0xFE + 1), 0x00]),
),
(
bytearray(range(1, 0xFF + 1)),
bytearray([0xFF, *range(1, 0xFE + 1), 0x02, 0xFF, 0x00]),
),
(
bytearray([*range(0x02, 0xFF + 1), 0x00]),
bytearray([0xFF, *range(2, 0xFF + 1), 0x01, 0x01, 0x00]),
),
(
bytearray([*range(0x03, 0xFF + 1), 0x00, 0x01]),
bytearray([0xFE, *range(0x03, 0xFF + 1), 0x02, 0x01, 0x00]),
),
]
 
 
def pretty_hex(bytes: bytearray, m: int, n: int) -> str:
if len(bytes) < m:
return bytes.hex(" ").upper()
return f"{bytes[:n].hex(' ').upper()} ... {bytes[-n:].hex(' ').upper()}"
 
 
def main():
for data, expect in EXAMPLES:
encoded = cob_encode(data)
assert encoded == expect
assert cob_decode(encoded) == data
print(f"{pretty_hex(data, 5, 3):<23} -> {pretty_hex(encoded, 7, 4):<33}")
 
 
if __name__ == "__main__":
main()
</syntaxhighlight>
 
{{out}}
<pre>
00 -> 01 01 00
00 00 -> 01 01 01 00
00 11 00 -> 01 02 11 01 00
11 22 00 33 -> 03 11 22 02 33 00
11 22 33 44 -> 05 11 22 33 44 00
11 00 00 00 -> 02 11 01 01 01 00
01 02 03 ... FC FD FE -> FF 01 02 03 ... FC FD FE 00
00 01 02 ... FC FD FE -> 01 FF 01 02 ... FC FD FE 00
01 02 03 ... FD FE FF -> FF 01 02 03 ... FE 02 FF 00
02 03 04 ... FE FF 00 -> FF 02 03 04 ... FF 01 01 00
03 04 05 ... FF 00 01 -> FE 03 04 05 ... FF 02 01 00
</pre>
 
=={{header|Raku}}==
{{trans|Wren}}
<syntaxhighlight lang="raku" line># 20231102 Raku programming solution
 
sub encode($data where $data.Bool, $delim = 0x00) {
my ($ins,$code,$addLastCode,@enc) = 0,1,True,-1;
for $data.list -> $byte {
if $byte != 0 { @enc.push($byte) andthen $code++ }
$addLastCode = True;
if $byte == 0 || $code == 255 {
$addLastCode = False if $code == 255;
@enc[$ins] = $code;
$code = 1;
$ins = @enc.elems;
@enc.push(-1);
}
}
if $addLastCode {
@enc[$ins] = $code;
if $delim != 0 { @enc >>^=>> $delim }
@enc.push($delim)
} else {
if $delim != 0 { @enc >>^=>> $delim }
@enc[$ins] = $delim
}
return @enc;
}
 
sub decode($data where $data.Bool, $delim = 0x00) {
my $length = ( my @enc2 = $data.list[0..*-2] ).elems;
if $delim != 0 { @enc2 >>^=>> $delim }
my ($block,$code,@dec) = 0,255;
for @enc2.kv -> $i,$byte {
if $block != 0 {
@dec.push($byte)
} else {
die "marker pointing beyond the end of the packet." if $i + $byte > $length;
@dec.push(0) if $code != 255;
$block = $code = $byte;
last if $code == 0
}
$block--;
}
return @dec;
}
 
for ( [0x00], [0x00,0x00], [0x00,0x11,0x00], [0x11,0x22,0x00,0x33],
[0x11,0x22,0x33,0x44], [0x11,0x00,0x00,0x00], # 0x01..0xfe, 0x00..0xfe,
# [0x02..0xff].append(0x00), [0x03..0xff].append(0x00, 0x01),
) { # https://crccalc.com/bytestuffing.php
# say encode( $_ )>>.&{.fmt("0x%x")};
say decode(encode( $_ ))>>.&{.fmt("0x%x")}
}</syntaxhighlight>
You may [https://ato.pxeger.com/run?1=nVTLjpswFF11w1fcydAKGuMAmZGqoqBRK3XVZXdRWjlgBhQCCEybKJMvmc0s2p9qf6Z-kToZumhZJPZ9nHPv9bEfv7dk0z89_ehZ5r35-eJX16-BVkmdUsdOCSPwLactBbnG7-q6RHxNy2ILC_B3vu_CwQKA7R4cu6g6ZItUZJM0_Ug69l5s7jieK8JRgD61PUVeEImcrG41bll0DLwY7PWeUQXIvyLThiueCwcQOLjpu9yRZhdIlbKcViA5p1M46kSTnfMKzugScyEwHx5UrtiFt7cn5ucYH0jZUZltxEd_wkVtSzGAFQ-WMYZT50Bg2ngsN8meaEm33QWYatQL3MEumzuCpZswyxvK_nsRIkOdmjFLiOPPizgePAr7jF55XMVMxQQO_wI4Wpb0WUNDLWV9W8mQyDpalpBfSv9HfnZJq3uWc7sjtgIxlHyDwJY-xq-9cAWuMfDRPsKxRqTC12WdbLTG73idStaDFISgZT7efJVyLtCIogWEZjOOnIOZ2h4O_Xzq_EsLCpMtaTe0haYuKlZU97Cm-7pKgV8GfndTqDO5bEiyoQxPJG0BU638eBhVNEbPJ3pS-dWlynXxi5OiJaIRUHJJnt0S31TvCcHzomcK4BVIBYghOrAUh7tC6h9dbILAsMhNGCLtm89XSHOdOedz_nNzY-Ro3AHqWugpwNjfZRRJbQ1r6_qE54fSmK0waRo-akdqUFU2H3FJoMBFFtcpZ8gZa7q3s1nSJgkpE5zU25mYYMf6LOMHiZu8UXQd2Q_PMNhfwI1j_OqAsy1zJv7u5W7iHiN5XUWcvi9m-Ei8dVRvvH7qhyf_Nw Attempt This Online!]
 
=={{header|Wren}}==
{{libheader|Wren-fmt}}
This only supports using a non-zero marker (seeusing the method suggested by Nigel Galloway in the talk page) which is also the method suggested in the original Cheshire & Baker paper.
<syntaxhighlight lang="ecmascriptwren">import "./fmt" for Fmt
 
class COBS {
static isByte(i) { (i is Num) && i.isInteger && i >= 0 && i < 256 }
 
static encode(data, delim) {
if (!((data is List) && data.count > 0 && data.all { |i| isByte(i) })) {
Fiber.abort("data must be a non-empty list of bytes.")
Line 340 ⟶ 885:
if (addLastCode) {
enc[ins] = code
if (delim != 0) for (i in 0...enc.count) enc[i] = enc[i] ^ delim
enc.add(0)
enc.add(delim)
} else {
if (delim != 0) for (i in 0...enc.count) enc[insi] = 0enc[i] ^ delim
enc[ins] = delim
}
return enc
}
 
static decode(enc, delim) {
if (!((enc is List) && enc.count > 0 && enc[-1] == 0delim &&
enc.all { |i| isByte(i) })) {
Fiber.abort("encoded data must be a non-empty list of zerodelimiter-terminated bytes.")
}
var enc2 = enc[0..-2]
var length = enc2.count
if (delim != 0) for (i in 0...length) enc2[i] = enc[i] ^ delim
var dec = []
var code = 255
var block = 0
for (bytei in enc[0..-2].length) {
var byte = enc2[i]
if (block != 0) {
dec.add(byte)
} else {
if (i + byte > length) Fiber.abort("marker pointing beyond the end of the packet.")
if (code != 255) dec.add(0)
code = byte
Line 384 ⟶ 936:
]
 
for (delim in [0x00, 0x02]) {
var encoded = []
var encoded = []
System.print("COBS encoding (hex):")
Fmt.print("COBS encoding (hex) with delimiter $#02x:", delim)
for (example in examples) {
varfor res = COBS.encode(example in examples) {
var res = COBS.encode(example, delim)
encoded.add(res)
encoded.add(res)
if (example.count < 5) {
if (example.count < 5) {
Fmt.print("$-33s -> $02X", Fmt.swrite("$02X", example), res)
Fmt.print("$-33s -> $02X", Fmt.swrite("$02X", example), res)
} else {
} else {
var e = Fmt.va("Xz", 2, example, 0, " ", "", "", 5, "...")
var re = Fmt.va("Xz", 2, resexample, 0, " ", "", "", 5, "...")
var r = Fmt.printva("$sXz", ->2, res, 0, " $s", e"", r"", 5, "...")
Fmt.print("$s -> $s", e, r)
}
}
Fmt.print("\nCOBS decoding (hex) with delimiter $#02x:", delim)
}
for (enc in encoded) {
System.print("\nCOBS decoding (hex):")
var res = COBS.decode(enc, delim)
for (enc in encoded) {
var res = COBS.decode if (enc.count < 7) {
Fmt.print("$-33s -> $02X", Fmt.swrite("$02X", enc), res)
if (enc.count < 7) {
} else {
Fmt.print("$-33s -> $02X", Fmt.swrite("$02X", enc), res)
var e = Fmt.va("Xz", 2, enc, 0, " ", "", "", 5, "...")
} else {
var er = Fmt.va("Xz", 2, encres, 0, " ", "", "", 5, "...")
var r = Fmt.vaprint("Xz",$s 2, res, 0, "-> $s", ""e, "", 5, "..."r)
Fmt.print("$s -> $s", e, r)}
}
System.print()
}</syntaxhighlight>
 
{{out}}
<pre>
COBS encoding (hex) with delimiter 0x00:
00 -> 01 01 00
00 00 -> 01 01 01 00
Line 424 ⟶ 979:
03 04 05 06 07 ... FD FE FF 00 01 -> FE 03 04 05 06 ... FE FF 02 01 00
 
COBS decoding (hex) with delimiter 0x00:
01 01 00 -> 00
01 01 01 00 -> 00 00
Line 436 ⟶ 991:
FF 02 03 04 05 ... FE FF 01 01 00 -> 02 03 04 05 06 ... FC FD FE FF 00
FE 03 04 05 06 ... FE FF 02 01 00 -> 03 04 05 06 07 ... FD FE FF 00 01
 
COBS encoding (hex) with delimiter 0x02:
00 -> 03 03 02
00 00 -> 03 03 03 02
00 11 00 -> 03 00 13 03 02
11 22 00 33 -> 01 13 20 00 31 02
11 22 33 44 -> 07 13 20 31 46 02
11 00 00 00 -> 00 13 03 03 03 02
01 02 03 04 05 ... FA FB FC FD FE -> FD 03 00 01 06 ... F9 FE FF FC 02
00 01 02 03 04 ... FA FB FC FD FE -> 03 FD 03 00 01 ... F9 FE FF FC 02
01 02 03 04 05 ... FB FC FD FE FF -> FD 03 00 01 06 ... FF FC 00 FD 02
02 03 04 05 06 ... FC FD FE FF 00 -> FD 00 01 06 07 ... FC FD 03 03 02
03 04 05 06 07 ... FD FE FF 00 01 -> FC 01 06 07 04 ... FC FD 00 03 02
 
COBS decoding (hex) with delimiter 0x02:
03 03 02 -> 00
03 03 03 02 -> 00 00
03 00 13 03 02 -> 00 11 00
01 13 20 00 31 02 -> 11 22 00 33
07 13 20 31 46 02 -> 11 22 33 44
00 13 03 03 03 02 -> 11 00 00 00
FD 03 00 01 06 ... F9 FE FF FC 02 -> 01 02 03 04 05 ... FA FB FC FD FE
03 FD 03 00 01 ... F9 FE FF FC 02 -> 00 01 02 03 04 ... FA FB FC FD FE
FD 03 00 01 06 ... FF FC 00 FD 02 -> 01 02 03 04 05 ... FB FC FD FE FF
FD 00 01 06 07 ... FC FD 03 03 02 -> 02 03 04 05 06 ... FC FD FE FF 00
FC 01 06 07 04 ... FC FD 00 03 02 -> 03 04 05 06 07 ... FD FE FF 00 01
</pre>
9,485

edits