blob: b983620287684483bf800b86ec06b16718a53aac [file] [log] [blame]
/*
* Copyright (C) 2019 Square, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package okio
interface BufferedSourceFactory {
class Pipe(
var sink: BufferedSink,
var source: BufferedSource
)
val isOneByteAtATime: Boolean
fun pipe(): Pipe
companion object {
val BUFFER: BufferedSourceFactory = object : BufferedSourceFactory {
override val isOneByteAtATime: Boolean
get() = false
override fun pipe(): Pipe {
val buffer = Buffer()
return Pipe(
buffer,
buffer
)
}
}
val REAL_BUFFERED_SOURCE: BufferedSourceFactory = object :
BufferedSourceFactory {
override val isOneByteAtATime: Boolean
get() = false
override fun pipe(): Pipe {
val buffer = Buffer()
return Pipe(
buffer,
(buffer as Source).buffer()
)
}
}
/**
* A factory deliberately written to create buffers whose internal segments are always 1 byte
* long. We like testing with these segments because are likely to trigger bugs!
*/
val ONE_BYTE_AT_A_TIME_BUFFERED_SOURCE: BufferedSourceFactory = object :
BufferedSourceFactory {
override val isOneByteAtATime: Boolean
get() = true
override fun pipe(): Pipe {
val buffer = Buffer()
return Pipe(
buffer,
object : Source by buffer {
override fun read(sink: Buffer, byteCount: Long): Long {
// Read one byte into a new buffer, then clone it so that the segment is shared.
// Shared segments cannot be compacted so we'll get a long chain of short segments.
val box = Buffer()
val result = buffer.read(box, minOf(byteCount, 1L))
if (result > 0L) sink.write(box.copy(), result)
return result
}
}.buffer()
)
}
}
val ONE_BYTE_AT_A_TIME_BUFFER: BufferedSourceFactory = object :
BufferedSourceFactory {
override val isOneByteAtATime: Boolean
get() = true
override fun pipe(): Pipe {
val buffer = Buffer()
return Pipe(
object : Sink by buffer {
override fun write(source: Buffer, byteCount: Long) {
// Write each byte into a new buffer, then clone it so that the segments are shared.
// Shared segments cannot be compacted so we'll get a long chain of short segments.
for (i in 0 until byteCount) {
val box = Buffer()
box.write(source, 1)
buffer.write(box.copy(), 1)
}
}
}.buffer(),
buffer
)
}
}
val PEEK_BUFFER: BufferedSourceFactory = object : BufferedSourceFactory {
override val isOneByteAtATime: Boolean
get() = false
override fun pipe(): Pipe {
val buffer = Buffer()
return Pipe(
buffer,
buffer.peek()
)
}
}
val PEEK_BUFFERED_SOURCE: BufferedSourceFactory = object :
BufferedSourceFactory {
override val isOneByteAtATime: Boolean
get() = false
override fun pipe(): Pipe {
val buffer = Buffer()
return Pipe(
buffer,
(buffer as Source).buffer().peek()
)
}
}
val PARAMETERIZED_TEST_VALUES = mutableListOf<Array<Any>>(
arrayOf(BUFFER),
arrayOf(REAL_BUFFERED_SOURCE),
arrayOf(ONE_BYTE_AT_A_TIME_BUFFERED_SOURCE),
arrayOf(ONE_BYTE_AT_A_TIME_BUFFER),
arrayOf(PEEK_BUFFER),
arrayOf(PEEK_BUFFERED_SOURCE)
)
}
}