static size_t
as_scan_command_init(uint8_t* cmd, const as_policy_scan* policy, const as_scan* scan,
	uint64_t task_id, uint16_t n_fields, as_buffer* argbuffer)
{
	uint8_t* p;
	
	if (scan->apply_each.function[0]) {
		p = as_command_write_header(cmd, AS_MSG_INFO1_READ, AS_MSG_INFO2_WRITE,
			AS_POLICY_COMMIT_LEVEL_ALL, AS_POLICY_CONSISTENCY_LEVEL_ONE, AS_POLICY_EXISTS_IGNORE,
			AS_POLICY_GEN_IGNORE, 0, 0, policy->timeout, n_fields, 0);
	}
	else {
		uint8_t read_attr = (scan->no_bins)? AS_MSG_INFO1_READ | AS_MSG_INFO1_GET_NOBINDATA : AS_MSG_INFO1_READ;
		p = as_command_write_header_read(cmd, read_attr, AS_POLICY_CONSISTENCY_LEVEL_ONE, policy->timeout, n_fields, scan->select.size);
	}
	
	if (scan->ns) {
		p = as_command_write_field_string(p, AS_FIELD_NAMESPACE, scan->ns);
	}
	
	if (scan->set) {
		p = as_command_write_field_string(p, AS_FIELD_SETNAME, scan->set);
	}
	
	// Write scan options
	p = as_command_write_field_header(p, AS_FIELD_SCAN_OPTIONS, 2);
	uint8_t priority = scan->priority << 4;
	
	if (policy->fail_on_cluster_change) {
		priority |= 0x08;
	}
	*p++ = priority;
	*p++ = scan->percent;
	
	// Write taskId field
	p = as_command_write_field_uint64(p, AS_FIELD_TASK_ID, task_id);
	
	// Write background function
	if (scan->apply_each.function[0]) {
		p = as_command_write_field_header(p, AS_FIELD_UDF_OP, 1);
		*p++ = 2;
		p = as_command_write_field_string(p, AS_FIELD_UDF_PACKAGE_NAME, scan->apply_each.module);
		p = as_command_write_field_string(p, AS_FIELD_UDF_FUNCTION, scan->apply_each.function);
		p = as_command_write_field_buffer(p, AS_FIELD_UDF_ARGLIST, argbuffer);
	}
    as_buffer_destroy(argbuffer);
	
	if (scan->select.size > 0) {
		for (uint16_t i = 0; i < scan->select.size; i++) {
			p = as_command_write_bin_name(p, scan->select.entries[i]);
		}
	}
	return as_command_write_end(cmd, p);
}
static size_t
as_scan_command_init(uint8_t* cmd, const as_policy_scan* policy, const as_scan* scan,
uint64_t task_id, uint16_t n_fields, as_buffer* argbuffer, uint32_t predexp_size)
{
	uint8_t* p;
	
	if (scan->apply_each.function[0]) {
		p = as_command_write_header(cmd, AS_MSG_INFO1_READ, AS_MSG_INFO2_WRITE, 0,
			AS_POLICY_COMMIT_LEVEL_ALL, AS_POLICY_EXISTS_IGNORE, AS_POLICY_GEN_IGNORE, 0, 0,
			policy->base.total_timeout, n_fields, 0, policy->durable_delete);
	}
	else {
		uint8_t read_attr = (scan->no_bins)? AS_MSG_INFO1_READ | AS_MSG_INFO1_GET_NOBINDATA : AS_MSG_INFO1_READ;
		p = as_command_write_header_read(cmd, read_attr, AS_POLICY_READ_MODE_AP_ONE,
			AS_POLICY_READ_MODE_SC_SESSION, policy->base.total_timeout, n_fields, scan->select.size);
	}
	
	if (scan->ns[0]) {
		p = as_command_write_field_string(p, AS_FIELD_NAMESPACE, scan->ns);
	}
	
	if (scan->set[0]) {
		p = as_command_write_field_string(p, AS_FIELD_SETNAME, scan->set);
	}

	// Write scan options
	p = as_command_write_field_header(p, AS_FIELD_SCAN_OPTIONS, 2);
	uint8_t priority = scan->priority << 4;
	
	if (policy->fail_on_cluster_change) {
		priority |= 0x08;
	}

	*p++ = priority;
	*p++ = scan->percent;

	// Write socket timeout.
	p = as_command_write_field_header(p, AS_FIELD_SCAN_TIMEOUT, sizeof(uint32_t));
	*(uint32_t*)p = cf_swap_to_be32(policy->base.socket_timeout);
	p += sizeof(uint32_t);

	// Write taskId field
	p = as_command_write_field_uint64(p, AS_FIELD_TASK_ID, task_id);
	
	// Write background function
	if (scan->apply_each.function[0]) {
		p = as_command_write_field_header(p, AS_FIELD_UDF_OP, 1);
		*p++ = 2;
		p = as_command_write_field_string(p, AS_FIELD_UDF_PACKAGE_NAME, scan->apply_each.module);
		p = as_command_write_field_string(p, AS_FIELD_UDF_FUNCTION, scan->apply_each.function);
		p = as_command_write_field_buffer(p, AS_FIELD_UDF_ARGLIST, argbuffer);
	}
    as_buffer_destroy(argbuffer);
	
	// Write predicate expressions.
	if (scan->predexp.size > 0) {
		p = as_command_write_field_header(p, AS_FIELD_PREDEXP, predexp_size);
		for (uint16_t ii = 0; ii < scan->predexp.size; ++ii) {
			as_predexp_base * bp = scan->predexp.entries[ii];
			p = (*bp->write_fn)(bp, p);
		}
	}
	
	if (scan->select.size > 0) {
		for (uint16_t i = 0; i < scan->select.size; i++) {
			p = as_command_write_bin_name(p, scan->select.entries[i]);
		}
	}

	return as_command_write_end(cmd, p);
}