Fatal error: Not enough bits to represent the passed value
Fatal error: Not enough bits to represent the passed value
尝试使用 Swift 中编写的 Mikrotik API 库:
https://wiki.mikrotik.com/wiki/API_in_Swift
当我发送小命令时效果很好
但是,如果我尝试发送大脚本字符串,则会出现错误:
Fatal error: Not enough bits to represent the passed value
崩溃的代码:
private func writeLen(_ command : String) -> Data {
let data = command.data(using: String.Encoding.utf8)
var len = data?.count ?? 0
var dat = Data()
if len < 0x80 {
dat.append([UInt8(len)], count: 1)
}else if len < 0x4000 {
len = len | 0x8000;
dat.append(Data(bytes: [UInt8(len >> 8)]))
dat.append(Data(bytes: [UInt8(len)]))
}else if len < 0x20000 {
len = len | 0xC00000;
dat.append(Data(bytes: [UInt8(len >> 16)]))
dat.append(Data(bytes: [UInt8(len >> 8)]))
dat.append(Data(bytes: [UInt8(len)]))
}
else if len < 0x10000000 {
len = len | 0xE0000000;
dat.append(Data(bytes: [UInt8(len >> 24)]))
dat.append(Data(bytes: [UInt8(len >> 16)]))
dat.append(Data(bytes: [UInt8(len >> 8)]))
dat.append(Data(bytes: [UInt8(len)]))
}else{
dat.append(Data(bytes: [0xF0]))
dat.append(Data(bytes: [UInt8(len >> 24)]))
dat.append(Data(bytes: [UInt8(len >> 16)]))
dat.append(Data(bytes: [UInt8(len >> 8)]))
dat.append(Data(bytes: [UInt8(len)]))
}
return dat
}
这部分出现致命错误:
else if len < 0x4000 {
len = len | 0x8000;
dat.append(Data(bytes: [UInt8(len >> 8)]))
dat.append(Data(bytes: [UInt8(len)]))
}
行:
dat.append(Data(bytes: [UInt8(len)]))
此时数据大小为1072字节,len等于33840,无法用len值初始化UInt8。
如何编辑代码以避免错误?
我正在使用 Swift 4.2
编辑:
这里有一个相同逻辑的例子,但是写在JavaScript
module.exports.encodeString = function encodeString(s) {
var data = null;
var len = Buffer.byteLength(s);
var offset = 0;
if (len < 0x80) {
data = new Buffer(len + 1);
data[offset++] = len;
} else if (len < 0x4000) {
data = new Buffer(len + 2);
len |= 0x8000;
data[offset++] = (len >> 8) & 0xff;
data[offset++] = len & 0xff;
} else if (len < 0x200000) {
data = new Buffer(len + 3);
len |= 0xC00000;
data[offset++] = (len >> 16) & 0xff;
data[offset++] = (len >> 8) & 0xff;
data[offset++] = len & 0xff;
} else if (len < 0x10000000) {
data = new Buffer(len + 4);
len |= 0xE0000000;
data[offset++] = (len >> 24) & 0xff;
data[offset++] = (len >> 16) & 0xff;
data[offset++] = (len >> 8) & 0xff;
data[offset++] = len & 0xff;
} else {
data = new Buffer(len + 5);
data[offset++] = 0xF0;
data[offset++] = (len >> 24) & 0xff;
data[offset++] = (len >> 16) & 0xff;
data[offset++] = (len >> 8) & 0xff;
data[offset++] = len & 0xff;
}
data.utf8Write(s, offset);
return data;
};
也许有人看出了区别
感谢 JavaScript 翻译。它清楚地显示了问题,因为 Swift 版本与它不相似。
让我们来看看 JavaScript 的这一段,因为它是您在 Swift 中绊倒的部分:
} else if (len < 0x4000) {
data = new Buffer(len + 2);
len |= 0x8000;
data[offset++] = (len >> 8) & 0xff;
data[offset++] = len & 0xff;
}
也就是 Swift 中的 "translated" 是这样的:
} else if len < 0x4000 {
len = len | 0x8000;
dat.append(Data(bytes: [UInt8(len >> 8)]))
dat.append(Data(bytes: [UInt8(len)]))
}
好吧,您可以立即看出它们完全不同。在最后一行,Swift 版本忘记了 & 0xff
.
如果你把它放进去,一切都会开始工作。我们也可以让它看起来更像 JavaScript 原来的样子:
} else if len < 0x4000 {
len |= 0x8000;
dat.append(Data(bytes: [UInt8(len >> 8)]))
dat.append(Data(bytes: [UInt8(len & 0xff)]))
}
所以我会说,是的,使用 JavaScript 作为指南,你会没事的。如果你觉得最后一行 "swifty" 不够,那么可以这样写:
dat.append(Data(bytes: [UInt8(truncatingIfNeeded: len)]))
完全一样的结果
我不保证在您进行这些更改后一切都会完美运行(您显示的 Swift 代码在我看来仍然与 JavaScript 执行相同的操作) ,但至少我们将长度字节写入数据开头的部分将正常工作。
尝试使用 Swift 中编写的 Mikrotik API 库: https://wiki.mikrotik.com/wiki/API_in_Swift
当我发送小命令时效果很好
但是,如果我尝试发送大脚本字符串,则会出现错误:
Fatal error: Not enough bits to represent the passed value
崩溃的代码:
private func writeLen(_ command : String) -> Data {
let data = command.data(using: String.Encoding.utf8)
var len = data?.count ?? 0
var dat = Data()
if len < 0x80 {
dat.append([UInt8(len)], count: 1)
}else if len < 0x4000 {
len = len | 0x8000;
dat.append(Data(bytes: [UInt8(len >> 8)]))
dat.append(Data(bytes: [UInt8(len)]))
}else if len < 0x20000 {
len = len | 0xC00000;
dat.append(Data(bytes: [UInt8(len >> 16)]))
dat.append(Data(bytes: [UInt8(len >> 8)]))
dat.append(Data(bytes: [UInt8(len)]))
}
else if len < 0x10000000 {
len = len | 0xE0000000;
dat.append(Data(bytes: [UInt8(len >> 24)]))
dat.append(Data(bytes: [UInt8(len >> 16)]))
dat.append(Data(bytes: [UInt8(len >> 8)]))
dat.append(Data(bytes: [UInt8(len)]))
}else{
dat.append(Data(bytes: [0xF0]))
dat.append(Data(bytes: [UInt8(len >> 24)]))
dat.append(Data(bytes: [UInt8(len >> 16)]))
dat.append(Data(bytes: [UInt8(len >> 8)]))
dat.append(Data(bytes: [UInt8(len)]))
}
return dat
}
这部分出现致命错误:
else if len < 0x4000 {
len = len | 0x8000;
dat.append(Data(bytes: [UInt8(len >> 8)]))
dat.append(Data(bytes: [UInt8(len)]))
}
行:
dat.append(Data(bytes: [UInt8(len)]))
此时数据大小为1072字节,len等于33840,无法用len值初始化UInt8。
如何编辑代码以避免错误?
我正在使用 Swift 4.2
编辑:
这里有一个相同逻辑的例子,但是写在JavaScript
module.exports.encodeString = function encodeString(s) {
var data = null;
var len = Buffer.byteLength(s);
var offset = 0;
if (len < 0x80) {
data = new Buffer(len + 1);
data[offset++] = len;
} else if (len < 0x4000) {
data = new Buffer(len + 2);
len |= 0x8000;
data[offset++] = (len >> 8) & 0xff;
data[offset++] = len & 0xff;
} else if (len < 0x200000) {
data = new Buffer(len + 3);
len |= 0xC00000;
data[offset++] = (len >> 16) & 0xff;
data[offset++] = (len >> 8) & 0xff;
data[offset++] = len & 0xff;
} else if (len < 0x10000000) {
data = new Buffer(len + 4);
len |= 0xE0000000;
data[offset++] = (len >> 24) & 0xff;
data[offset++] = (len >> 16) & 0xff;
data[offset++] = (len >> 8) & 0xff;
data[offset++] = len & 0xff;
} else {
data = new Buffer(len + 5);
data[offset++] = 0xF0;
data[offset++] = (len >> 24) & 0xff;
data[offset++] = (len >> 16) & 0xff;
data[offset++] = (len >> 8) & 0xff;
data[offset++] = len & 0xff;
}
data.utf8Write(s, offset);
return data;
};
也许有人看出了区别
感谢 JavaScript 翻译。它清楚地显示了问题,因为 Swift 版本与它不相似。
让我们来看看 JavaScript 的这一段,因为它是您在 Swift 中绊倒的部分:
} else if (len < 0x4000) {
data = new Buffer(len + 2);
len |= 0x8000;
data[offset++] = (len >> 8) & 0xff;
data[offset++] = len & 0xff;
}
也就是 Swift 中的 "translated" 是这样的:
} else if len < 0x4000 {
len = len | 0x8000;
dat.append(Data(bytes: [UInt8(len >> 8)]))
dat.append(Data(bytes: [UInt8(len)]))
}
好吧,您可以立即看出它们完全不同。在最后一行,Swift 版本忘记了 & 0xff
.
如果你把它放进去,一切都会开始工作。我们也可以让它看起来更像 JavaScript 原来的样子:
} else if len < 0x4000 {
len |= 0x8000;
dat.append(Data(bytes: [UInt8(len >> 8)]))
dat.append(Data(bytes: [UInt8(len & 0xff)]))
}
所以我会说,是的,使用 JavaScript 作为指南,你会没事的。如果你觉得最后一行 "swifty" 不够,那么可以这样写:
dat.append(Data(bytes: [UInt8(truncatingIfNeeded: len)]))
完全一样的结果
我不保证在您进行这些更改后一切都会完美运行(您显示的 Swift 代码在我看来仍然与 JavaScript 执行相同的操作) ,但至少我们将长度字节写入数据开头的部分将正常工作。