summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--internal/contentenc/offsets.go16
-rw-r--r--internal/contentenc/offsets_test.go47
2 files changed, 32 insertions, 31 deletions
diff --git a/internal/contentenc/offsets.go b/internal/contentenc/offsets.go
index 7487baf..3a0abf3 100644
--- a/internal/contentenc/offsets.go
+++ b/internal/contentenc/offsets.go
@@ -76,20 +76,20 @@ func (be *ContentEnc) CipherSizeToPlainSize(cipherSize uint64) uint64 {
return cipherSize - overhead
}
-// PlainSizeToCipherSize calculates the ciphertext size from a plaintext size
+// PlainSizeToCipherSize calculates the ciphertext size from a plaintext size.
func (be *ContentEnc) PlainSizeToCipherSize(plainSize uint64) uint64 {
// Zero-sized files stay zero-sized
if plainSize == 0 {
return 0
}
+ return be.PlainOffToCipherOff(plainSize-1) + 1
+}
- // Block number at last byte
- blockNo := be.PlainOffToBlockNo(plainSize - 1)
- blockCount := blockNo + 1
-
- overhead := be.BlockOverhead()*blockCount + HeaderLen
-
- return plainSize + overhead
+// PlainOffToCipherOff tells you the highest ciphertext offset that is
+// *guaranteed* to be written/read when you write/read at `plainOff`.
+func (be *ContentEnc) PlainOffToCipherOff(plainOff uint64) uint64 {
+ startOfBlock := be.BlockNoToCipherOff(be.PlainOffToBlockNo(plainOff))
+ return startOfBlock + plainOff%be.PlainBS() + be.BlockOverhead()
}
// ExplodePlainRange splits a plaintext byte range into (possibly partial) blocks
diff --git a/internal/contentenc/offsets_test.go b/internal/contentenc/offsets_test.go
index 4bc3762..c3b8fcd 100644
--- a/internal/contentenc/offsets_test.go
+++ b/internal/contentenc/offsets_test.go
@@ -15,38 +15,39 @@ func TestSizeToSize(t *testing.T) {
const rangeMax = 10000
- var c2p [rangeMax]uint64
- var p2c [rangeMax]uint64
+ // y values in this order:
+ // 0 ... CipherSizeToPlainSize
+ // 1 ... PlainSizeToCipherSize
+ // 2 ... PlainOffToCipherOff
+ var yTable [rangeMax][3]uint64
// Calculate values
- for i := range c2p {
- c2p[i] = ce.CipherSizeToPlainSize(uint64(i))
- p2c[i] = ce.PlainSizeToCipherSize(uint64(i))
+ for x := range yTable {
+ yTable[x][0] = ce.CipherSizeToPlainSize(uint64(x))
+ yTable[x][1] = ce.PlainSizeToCipherSize(uint64(x))
+ yTable[x][2] = ce.PlainOffToCipherOff(uint64(x))
}
// Print data table
- fmt.Print("x\tToPlainSize\tToCipherSize\n")
- for i := range c2p {
- if i > 1 && i < rangeMax-1 {
+ fmt.Print("x\tCipherSizeToPlainSize\tPlainSizeToCipherSize\tPlainOffToCipherOff\n")
+ for x := range yTable {
+ if x > 1 && x < rangeMax-1 {
// If the point before has value-1 and the point after has value+1,
// it is not interesting. Don't print it out.
- if c2p[i] == c2p[i-1]+1 && p2c[i] == p2c[i-1]+1 && c2p[i+1] == c2p[i]+1 && p2c[i+1] == p2c[i]+1 {
+ interesting := false
+ for i := 0; i <= 2; i++ {
+ if yTable[x-1][i]+1 != yTable[x][i] && yTable[x][i]+1 != yTable[x+1][i]+1 {
+ interesting = true
+ }
+ // Monotonicity check
+ if yTable[x][i] < yTable[x-1][i] {
+ t.Errorf("column %d is non-monotonic!", i)
+ }
+ }
+ if !interesting {
continue
}
}
- fmt.Printf("%d\t%d\t%d\n", i, c2p[i], p2c[i])
- }
-
- // Monotonicity check
- for i := range c2p {
- if i < 1 {
- continue
- }
- if c2p[i-1] > c2p[i] {
- t.Errorf("error: c2p is non-monotonic: c2p[%d]=%d c2p[%d]=%d ", i-1, c2p[i-1], i, c2p[i])
- }
- if p2c[i-1] > p2c[i] {
- t.Errorf("error: p2c is non-monotonic: p2c[%d]=%d p2c[%d]=%d ", i-1, p2c[i-1], i, p2c[i])
- }
+ fmt.Printf("%d\t%d\t%d\t%d\n", x, yTable[x][0], yTable[x][1], yTable[x][2])
}
}