Rust LogoBlog Engine

A blog engine is a content management system (CMS) specifically designed for publishing and managing blog posts. It provides the necessary tools and infrastructure for users (bloggers) to create, edit, publish, and organize their articles, and for readers to view and interact with that content.

Core Functionality of a Blog Engine:
1. Content Creation and Editing (CMS): A user-friendly interface for writing and formatting blog posts, often including rich text editors, image uploads, and tagging/categorization features.
2. Data Storage: A mechanism to persist blog posts, comments, user data, and other information. This typically involves a database (e.g., PostgreSQL, MySQL, MongoDB).
3. Content Display (Frontend): Rendering blog posts in a readable and aesthetically pleasing format on a public-facing website. This involves templating engines, styling (CSS), and responsiveness for various devices.
4. Routing and Permalinks: Assigning unique, human-readable URLs (permalinks) to each blog post, allowing direct access and better search engine optimization (SEO).
5. User Management and Authentication: For multi-user blogs, this includes user registration, login, role-based access control (e.g., author, editor, administrator), and comment moderation.
6. Commenting System: Allowing readers to post comments on articles, often with moderation capabilities for the blog owner.
7. Search and Organization: Features like search bars, categories, tags, and archives to help readers navigate and find specific content.
8. Media Management: Handling images, videos, and other media files associated with blog posts.

How it Works (Simplified Flow):
1. An author logs into the blog engine's admin panel.
2. They create a new post, write content, add tags, and set a publish date.
3. The blog engine stores this post data in its database.
4. When a reader visits the blog's website, the engine retrieves posts from the database.
5. It uses templating to format the data into HTML.
6. The generated HTML is sent to the reader's browser for display.

Rust Example Focus:
The provided Rust code snippet demonstrates a highly simplified, in-memory blog engine focusing on the core data structures and basic CRUD (Create, Read, Update, Delete) operations. It does not include a web interface, database persistence, user authentication, or a full templating system. Instead, it illustrates:
* `Post` Struct: Defines the structure of a blog post, including a unique ID, title, content, author, and timestamps.
* `BlogEngine` Struct: Manages a collection of `Post` objects using an `HashMap` for efficient storage and retrieval by ID.
* Basic API: Methods like `create_post`, `get_post`, `list_posts`, `update_post`, and `delete_post` to interact with the blog's content.
* Error Handling: Uses Rust's `Result` type and a custom `BlogError` enum for robust error reporting.
* Dependencies: Utilizes the `chrono` crate for date and time handling and the `uuid` crate for generating unique identifiers for posts.

This example serves as a foundational backend logic layer that could be extended with a web framework (like Actix Web, Axum, or Rocket) for a full-fledged web application, a database integration, and an actual frontend.

Example Code

```rust
use std::collections::HashMap;
use chrono::{Utc, DateTime};
use uuid::Uuid;

// Dependencies needed in Cargo.toml:
// [dependencies]
// chrono = "0.4"
// uuid = { version = "1.0", features = ["v4"] }

/// Represents a single blog post.
#[derive(Debug, Clone)]
struct Post {
    id: Uuid,
    title: String,
    content: String,
    author: String,
    published_date: DateTime<Utc>,
    last_updated_date: DateTime<Utc>,
}

impl Post {
    /// Creates a new blog post.
    fn new(title: String, content: String, author: String) -> Self {
        let now = Utc::now();
        Post {
            id: Uuid::new_v4(),
            title,
            content,
            author,
            published_date: now,
            last_updated_date: now,
        }
    }
}

/// Custom error types for blog engine operations.
#[derive(Debug)]
enum BlogError {
    PostNotFound,
    InvalidInput,
    // In a real application, more error types (e.g., DatabaseError, AuthError) would be added.
}

/// A type alias for results returned by blog engine operations.
type BlogResult<T> = Result<T, BlogError>;

/// The core blog engine responsible for managing posts.
struct BlogEngine {
    posts: HashMap<Uuid, Post>,
}

impl BlogEngine {
    /// Creates a new, empty BlogEngine.
    fn new() -> Self {
        BlogEngine {
            posts: HashMap::new(),
        }
    }

    /// Creates and adds a new post to the engine.
    /// Returns the created Post or an error if input is invalid.
    fn create_post(&mut self, title: String, content: String, author: String) -> BlogResult<Post> {
        if title.is_empty() || content.is_empty() || author.is_empty() {
            return Err(BlogError::InvalidInput);
        }
        let post = Post::new(title, content, author);
        self.posts.insert(post.id, post.clone());
        Ok(post)
    }

    /// Retrieves a post by its unique ID.
    /// Returns the Post or PostNotFound error if not found.
    fn get_post(&self, id: &Uuid) -> BlogResult<Post> {
        self.posts.get(id).cloned().ok_or(BlogError::PostNotFound)
    }

    /// Returns a list of all posts, sorted by published date (most recent first).
    fn list_posts(&self) -> Vec<Post> {
        let mut posts: Vec<Post> = self.posts.values().cloned().collect();
        posts.sort_by(|a, b| b.published_date.cmp(&a.published_date));
        posts
    }

    /// Updates an existing post with new title or content.
    /// Returns the updated Post or an error if not found or input is invalid.
    fn update_post(&mut self, id: &Uuid, new_title: Option<String>, new_content: Option<String>) -> BlogResult<Post> {
        let post = self.posts.get_mut(id).ok_or(BlogError::PostNotFound)?;

        let mut changed = false;
        if let Some(title) = new_title {
            if title.is_empty() { return Err(BlogError::InvalidInput); }
            post.title = title;
            changed = true;
        }
        if let Some(content) = new_content {
            if content.is_empty() { return Err(BlogError::InvalidInput); }
            post.content = content;
            changed = true;
        }

        if changed {
            post.last_updated_date = Utc::now();
        }
        Ok(post.clone())
    }

    /// Deletes a post by its unique ID.
    /// Returns Ok(()) on success or PostNotFound error if not found.
    fn delete_post(&mut self, id: &Uuid) -> BlogResult<()> {
        if self.posts.remove(id).is_some() {
            Ok(())
        } else {
            Err(BlogError::PostNotFound)
        }
    }
}

fn main() {
    let mut blog_engine = BlogEngine::new();

    println!("--- Creating Posts ---");
    // Create first post
    let post1_result = blog_engine.create_post(
        "My First Blog Post".to_string(),
        "This is the content of my very first blog post. It's exciting!".to_string(),
        "Alice".to_string(),
    );
    let post1_id = post1_result.expect("Failed to create Post 1").id;
    println!("Created Post 1 with ID: {}", post1_id);

    // Create second post
    let post2_result = blog_engine.create_post(
        "A Recipe for Success".to_string(),
        "To succeed, you need dedication, hard work, and a bit of luck.".to_string(),
        "Bob".to_string(),
    );
    let post2_id = post2_result.expect("Failed to create Post 2").id;
    println!("Created Post 2 with ID: {}", post2_id);

    // Attempt to create a post with invalid input
    let post_invalid_res = blog_engine.create_post(
        "".to_string(), // Empty title
        "Some content".to_string(),
        "Charlie".to_string(),
    );
    if let Err(e) = post_invalid_res {
        println!("Attempted to create post with invalid input: {:?}", e);
    }

    println!("\n--- Listing All Posts ---");
    for post in blog_engine.list_posts() {
        println!(
            "  - ID: {}, Title: '{}', Author: '{}', Published: {}",
            post.id,
            post.title,
            post.author,
            post.published_date.format("%Y-%m-%d %H:%M:%S")
        );
    }

    println!("\n--- Getting a Specific Post ---");
    match blog_engine.get_post(&post1_id) {
        Ok(post) => println!("  Found post: ID: {}, Title: '{}'", post.id, post.title),
        Err(e) => println!("  Error getting post: {:?}", e),
    }

    println!("\n--- Updating a Post ---");
    match blog_engine.update_post(
        &post1_id,
        Some("Updated First Blog Post Title".to_string()),
        Some("This content has been updated and is now even better!".to_string()),
    ) {
        Ok(post) => println!("  Updated post: ID: {}, New Title: '{}', New Content: '{}'", post.id, post.title, post.content),
        Err(e) => println!("  Error updating post: {:?}", e),
    }

    println!("\n--- Listing All Posts After Update ---");
    for post in blog_engine.list_posts() {
        println!(
            "  - ID: {}, Title: '{}', Author: '{}', Last Updated: {}",
            post.id,
            post.title,
            post.author,
            post.last_updated_date.format("%Y-%m-%d %H:%M:%S")
        );
    }

    println!("\n--- Deleting a Post ---");
    match blog_engine.delete_post(&post2_id) {
        Ok(_) => println!("  Post with ID {} deleted successfully.", post2_id),
        Err(e) => println!("  Error deleting post: {:?}", e),
    }

    println!("\n--- Listing All Posts After Deletion ---");
    for post in blog_engine.list_posts() {
        println!(
            "  - ID: {}, Title: '{}', Author: '{}', Published: {}",
            post.id,
            post.title,
            post.author,
            post.published_date.format("%Y-%m-%d %H:%M:%S")
        );
    }

    println!("\n--- Trying to get deleted post ---");
    match blog_engine.get_post(&post2_id) {
        Ok(post) => println!("  Found post: ID: {}, Title: '{}'", post.id, post.title),
        Err(e) => println!("  Error getting post: {:?}", e),
    }

    println!("\n--- Trying to update a non-existent post ---");
    let non_existent_id = Uuid::new_v4();
    match blog_engine.update_post(&non_existent_id, Some("Non Existent Update".to_string()), None) {
        Ok(_) => println!("  Unexpectedly updated non-existent post."),
        Err(e) => println!("  Correctly failed to update non-existent post: {:?}", e),
    }
}
```